xcode 在没有符号的设备上调试 iOS 应用程序

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10777244/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 00:25:27  来源:igfitidea点击:

Debug iOS application on device without symbols

iosxcodedelphilldb

提问by Allen Bauer

I need to debug the startup for an ios application on an actual device... and by start up I mean the very first instructionthat is is executed when the OS hands control over to the app. Not "main". Also, this application doesn't have any symbols (ie. the debug information isn't available.. yet). I don't care if I have to debug at the CPU instruction level. I know how to do that (done it for over 30 years). I want the debugger to stopwhen control is about to transfer to the app. When I use the Attach|by Name command and run, it just says "Finished running".

我需要在实际设备上调试 ios 应用程序的启动......我所说的启动是指当操作系统将控制权交给应用程序时执行的第一条指令。不是“主要”。此外,这个应用程序没有任何符号(即调试信息不​​可用......还没有)。我不在乎是否必须在 CPU 指令级别进行调试。我知道怎么做(做了 30 多年)。我希望调试器在控制即将转移到应用程序时停止。当我使用 Attach|by Name 命令并运行时,它只显示“已完成运行”。

Oh, and this application was not built in XCode. It is, however an application I built, signed and provisioned and moved to the device. The application does run since I can see the console output. Just in case you're thinking I'm some hacker trying to debug someone's application.

哦,这个应用程序不是用 XCode 构建的。然而,它我构建、签名和配置并移动到设备的应用程序。该应用程序确实运行了,因为我可以看到控制台输出。以防万一你认为我是一个试图调试某人应用程序的黑客。

How's that for a tall order? I'll bet nobody can answer this... I've not been able to find any information on how I could do this with an XCode-built project. I wonder if it is simply not possible or "allowed" by the Apple overlords?

这么高的订单怎么样?我敢打赌没有人能回答这个问题……我找不到任何关于如何使用 XCode 构建的项目来做到这一点的信息。我想知道这是苹果霸主根本不可能或“允许”的吗?

What do you say, Stack Overflow gods?

你说呢,Stack Overflow 的大神们?

UPDATE: I should clarify something. This application is notbuilt with any commercially available or open-source tool. I work with a tools vendor creating compilers, frameworks, and IDEs. IOW, you cannot get this tool... yet. In the process of bootstrapping a new tool chain, one regularly must resort to some very low-level raw debugging. Especially if there are bugs in the code generated by the tools.

更新:我应该澄清一些事情。此应用程序不是使用任何商用或开源工具构建的。我与一家工具供应商合作,创建编译器、框架和 IDE。IOW,你还不能得到这个工具......还没有。在引导新工具链的过程中,人们必须经常求助于一些非常低级的原始调试。特别是如果工具生成的代码中存在错误。

回答by Allen Bauer

I'm going to answer my own question because I think I've stumbled upon a solution. If anyone has anything more elegant and simple than this, please answer as well. On to the steps:

我要回答我自己的问题,因为我想我已经偶然发现了一个解决方案。如果有人有比这更优雅和简单的东西,也请回答。进入步骤:

Starting with a raw monolithic iOS executable (not a bundled .app, but the actual binary mach-o file that is the machine code).

从原始的整体式 iOS 可执行文件(不是捆绑的 .app,而是作为机器代码的实际二进制 mach-o 文件)开始。

  1. Create a new like-named empty Xcode project. Build and run it on the device.
  2. Locate the output bundle's .app folder.
  3. Copy the above raw iOS executable over the existing one in the .app bundle's folder.
  4. The application will now have an invalid signature and cannot be deployed and run.
  5. Run codesign against the app bundle (you can find out the command-line by running xcodebuild on the above Xcode project).
  6. In the bundle's .app folder, run otool -h -l on the binary image. Locate the LC_UNIXTHREAD load command and find the value associated with the 'pc' register. This is address where the os loader will jump to your application. If this address is odd, then these are Thumb instructions otherwise it will be ARM (I think that's how it works).
  7. Add a symbolic breakpoint (I used GDB instead of LLDB) and enter the address as '*0x00001234' as the symbol.
  8. Select Product|Perform Action|Run Without Building.
  1. 创建一个新的同名空 Xcode 项目。在设备上构建并运行它。
  2. 找到输出包的 .app 文件夹。
  3. 将上述原始 iOS 可执行文件复制到 .app 包文件夹中的现有可执行文件上。
  4. 该应用程序现在将具有无效签名并且无法部署和运行。
  5. 针对应用程序包运行 codesign(您可以通过在上述 Xcode 项目上运行 xcodebuild 来找到命令行)。
  6. 在包的 .app 文件夹中,对二进制映像运行 otool -h -l。找到 LC_UNIXTHREAD 加载命令并找到与“pc”寄存器关联的值。这是操作系统加载器将跳转到您的应用程序的地址。如果这个地址是奇数,那么这些是 Thumb 指令,否则它将是 ARM(我认为它是这样工作的)。
  7. 添加符号断点(我使用 GDB 而不是 LLDB)并输入地址为 '*0x00001234' 作为符号。
  8. 选择产品|执行操作|无需构建即可运行。

Assuming that GDB is able to evaluate the breakpoint expression and set the break point, and you've selected Product|Debug Workflow|Show Disassembly When Debugging, the process should break at the very first instruction to be executed in the application.

假设 GDB 能够计算断点表达式并设置断点,并且您选择了产品|调试工作流|在调试时显示反汇编,进程应该在应用程序中要执行的第一条指令处中断。

You can now single step the instructions and use the GDB console to get/set register values.

您现在可以单步执行指令并使用 GDB 控制台来获取/设置寄存器值。

回答by Kendall Helmstetter Gelner

Your question does not make sense - main is the entry point into the application. It is the first code that should be encountered, unless possibly you have initialize() overridden for some classes (but even then I think main would get hit before the runtime).

您的问题没有意义 - main 是应用程序的入口点。这是应该遇到的第一个代码,除非您可能为某些类重写了 initialize() (但即使如此,我认为 main 会在运行时之前被命中)。

I think you are seeing some kind of odd error on launch and you think you want to set a breakpoint on entry to catch it, but far more likely what would help you is to describe the problem on launch and let one of the 4000 people who have seen and fixed the same crash help you...

我认为您在发布时看到了某种奇怪的错误,并且您认为您想在进入时设置一个断点来捕获它,但更有可能帮助您的是在发布时描述问题并让 4000 人中的一个已经看到并修复了相同的崩溃帮助你......

However, if you really want to use GDB to break on an application with no symbols (but that you launch from XCode) you can have GDB break on an assembly address as per:

但是,如果您真的想使用 GDB 在没有符号的应用程序上中断(但您从 XCode 启动),您可以按照以下方式在程序集地址上中断 GDB:

How to break on assembly instruction at a given address in gdb?

如何在gdb中的给定地址处中断汇编指令?

To find the address of main (or other methods) you can use tool or atos, some examples in this question:

要查找主要(或其他方法)的地址,您可以使用工具或atos,此问题中的一些示例:

Matching up offsets in iOS crash dump to disassembled binary

将 iOS 故障转储中的偏移量与反汇编的二进制文件相匹配

ADDITION:

添加:

If for some reason XCode cannot launch your application for debugging, you could also jailbreak and install GDB on the device itself which would give complete control over debugging. If XCode can launch you application I see no reason why being able to break at an arbitrary memory address does not give you the ability you seek...

如果由于某种原因 XCode 无法启动您的应用程序进行调试,您还可以越狱并在设备上安装 GDB,这将完全控制调试。如果 XCode 可以启动您的应用程序,我看不出为什么能够在任意内存地址处中断不会给您提供您寻求的能力...

回答by Kendall Helmstetter Gelner

One solution for applications with webviews is to run them in the iOS Simulator, and connect to that with the remote-debugger in macOS Safari. This is off-topic but maybe the one or other could benefit.

具有 webviews 的应用程序的一种解决方案是在 iOS 模拟器中运行它们,并使用 macOS Safari 中的远程调试器连接到它。这是题外话,但也许其中一个可能会受益。

http://hiediutley.com/2011/11/22/debugging-ios-apps-using-safari-web-inspector/

http://hiediutley.com/2011/11/22/debugging-ios-apps-using-safari-web-inspector/

Or use NetCat for iOS... not the most perfect solution, but at least you see what's going on.

或者使用适用于 iOS 的 NetCat... 不是最完美的解决方案,但至少您可以看到发生了什么。