Apples GCC在哪里/如何将DWARF存储在可执行文件中

Alb*_*ert 11 macos gcc objdump dwarf dsymutil

Apple GCC在哪里/如何将DWARF存储在可执行文件中?

我编译了一个二进制文件gcc -gdwarf-2(Apples GCC).但是,既没有objdump -gobjdump -h没有向我显示任何调试信息.

libbfd也找不到任何调试信息.(我在binutils-mailinglist上问过这个问题.)

然而,我能够通过dsymutil(进入dSYM)提取调试信息.libbfd也可以读取那些调试信息.

Jas*_*nda 48

在Mac OS X上,决定让链接器(ld)在链接程序时不处理所有调试信息.调试信息通常是程序可执行文件大小的10倍,因此让链接器处理所有调试信息并将其包含在可执行二进制文件中会严重损害链接时间.对于迭代开发 - 编译,链接,编译,链接,调试,编译链接 - 这是一个真正的打击.

相反,编译器在.s文件中生成DWARF调试信息,汇编器在.o文件中输出它,链接器在可执行二进制文件中包含一个"调试映射",它告诉调试信息用户所有符号在哪里重新定位链接.

使用者(执行.o文件调试)从可执行文件加载调试映射并根据需要处理.o文件中的所有DWARF,根据调试映射的说明重新映射符号.

dsymutil可以被认为是一个调试信息链接器.它执行相同的过程 - 读取调试映射,从.o文件加载DWARF,重新定位所有地址 - 然后在最终的链接地址输出所有DWARF的单个二进制文件.这是dSYM捆绑包.

一旦你有了一个dSYM软件包,你就可以得到普通的标准DWARF,任何矮人阅读工具(可以处理Mach-O二进制文件)都可以处理.

有一个额外的改进使所有这些工作,UUID包含在Mach-O二进制文件中.每次链接器创建二进制文件时,它都会在LC_UUID加载命令(v.otool -hlvdwarfdump --uuid)中发出128位UUID .这唯一标识该二进制文件.当dsymutil创建的dSYM,它包括UUID.调试器只会将dSYM和可执行文件关联起来,如果它们具有匹配的UUID - 没有狡猾的文件模式时间戳或类似的东西.

我们还可以使用UUID来定位二进制文​​件的dSYM.它们显示在崩溃报告中,我们包含可用于搜索它们的Spotlight导入程序,例如, mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1" 如果dSYM位于Spotlight索引位置.您甚至可以为您的公司拥有一个dSYM存储库,以及一个可以在给定UUID的情况下检索正确dSYM的程序 - 可能是一个小的mysql数据库或类似的东西 - 所以您在随机可执行文件上运行调试器并立即进行所有调试该可执行文件的信息.你可以用UUID做一些非常巧妙的事情.

但无论如何,要回答您的原始问题:未提取的二进制文件具有调试映射,.o文件具有DWARF,并且dsymutil运行时这些组合以创建dSYM包.

如果你想看到调试映射条目,那么nm -pa executable它们就在那里.它们是旧的stabs nlist记录的形式 - 链接器已经知道如何处理stabs,因此最容易使用它们 - 但你会看到它如何工作没有太多麻烦,如果你是的话可能会参考一些stabs文档不确定.

  • 在使用 .o 文件的文件名剥离之前,可执行文件中有“调试映射”条目。`nm -pa 二进制 | grep OSO` 将列出它们。它们采用旧的 stabs 调试格式(因为链接器已经知道如何处理该格式)。创建 dSYM 后,您可以将它们从可执行文件中删除。你不需要在 Mac 平台上使用 `-g3`,`-g` 就足够了。我认为 `-g3` 会输出预处理宏信息,但 lldb 不会在 Mac OS X 上读取它(我不知道 clang 是否会输出它。) (3认同)
  • @JasonMolenda多么好的答案,谢谢!除了你和[这](http://wiki.dwarfstd.org/index.php?title=Apple's_%22Lazy%22_DWARF_Scheme)轶事写作我似乎找不到任何正式的,你知道吗?有什么? (2认同)