32

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

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

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

你说什么,堆栈溢出之神?

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

4

3 回答 3

23

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

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

  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. 选择产品|执行操作|运行而不构建。

假设 GDB 能够计算断点表达式并设置断点,并且您选择了 Product|Debug Workflow|Show Disassembly When Debugging,该进程应该在应用程序中执行的第一条指令处中断。

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

于 2012-05-28T23:50:54.210 回答
2

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

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

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

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

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

将 iOS 崩溃转储中的偏移量匹配到反汇编的二进制文件

添加:

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

于 2012-05-27T21:13:18.003 回答
1

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

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

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

于 2012-05-28T16:53:00.877 回答