苹果GCC在哪里/如何将DWARF存储在可执行文件中?我通过gcc -gdwarf-2(苹果GCC)编译了一个二进制文件。然而,objdump -g和objdump -h都没有显示任何调试信息。libbfd也没有找到任何调试信息。(我在binutils-mailinglist上询问了here。)但是我可以通过dsymutil提取调试信息(到dSYM中)。libbfd也可以读取这些调试信息。
gcc -gdwarf-2
objdump -g
objdump -h
dsymutil
jm81lzqq1#
在Mac OS X上,当你链接程序时,有一个决定是让链接器id不处理所有的调试信息。调试信息通常是程序可执行文件的大小的10x,所以让链接器处理所有的调试信息并将其包含在可执行文件的二进制文件中是对链接时间的严重损害。对于迭代开发-编译,链接,编译,链接,调试,编译链接-这是一个真实的的打击。相反,编译器在.s文件中生成DWARF调试信息,汇编器在.o文件中输出它,链接器在可执行二进制文件中包含一个“调试Map”,它告诉调试信息用户在链接过程中所有符号的位置。消费者(执行. o文件调试)从可执行文件加载调试Map,并根据需要处理.o文件中的所有DWARF,根据调试Map的指令重新Map符号。dsymutil可以被认为是一个调试信息链接器。它执行相同的过程--读取调试Map,从.o文件加载DWARF,重新定位所有地址--然后输出所有DWARF的最终链接地址的一个二进制文件。这就是dSYM包。一旦有了dSYM包,就有了任何dwarf阅读工具(可以处理Mach-O二进制文件)都可以处理的普通旧标准DWARF。还有一个额外的改进使得所有这些工作都能进行,即Mach-O二进制文件中包含的UUID(v. otool -hlv或dwarfdump --uuid)。这唯一地标识该二进制文件。当dsymutil创建dSYM时,调试器只会在dSYM和可执行文件有匹配的UUID时将它们关联起来--没有可疑的文件mod时间戳或类似的东西。我们还可以使用UUID来定位二进制文件的dSYM。它们会显示在崩溃报告中,我们包含了一个Spotlight导入器,您可以使用它来搜索它们,例如,如果dSYM位于Spotlight索引位置,则为mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1"。您甚至可以为您的公司创建一个dSYM存储库,并使用一个程序在给定UUID的情况下检索正确的dSYM-也许是一个小的mysql数据库或类似的东西-所以你在一个随机的可执行文件上运行调试器,你立刻就有了这个可执行文件的所有调试信息。不管怎样,回答你最初的问题:未剥离的二进制文件具有调试Map,.o文件具有DWARF,当运行dsymutil时,这些文件被组合以创建dSYM包。如果你想看到调试Map条目,执行nm -pa executable,它们都在那里。它们以旧的stabs nlist记录的形式存在--链接器已经知道如何处理stabs,所以使用它们是最容易的--但是你会看到它是如何工作的,没有太大的麻烦,如果你不确定,也许可以参考一些stabs文档。
id
10x
DWARF
otool -hlv
dwarfdump --uuid
mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1"
nm -pa executable
nlist
hkmswyz62#
似乎并没有。我跟踪了dsymutil,它读取了所有的*.o文件。objdump -h还列出了其中的所有调试信息。所以看起来这些信息没有被复制到二进制文件中。关于这一点的一些相关评论也可以在here中找到。
*.o
sr4lhrrt3#
OSX似乎有两种方法来放置调试信息:1.在用于编译的.o目标文件中。二进制文件存储对这些文件的引用(通过绝对路径)。1.在一个名为.dSYM的单独捆绑包(目录)中如果我用苹果的Clang编译,使用g++ -g main.cpp -o foo,我得到的包名为foo.dSYM。然而,如果我使用CMake,我得到的调试信息在对象文件中。我猜是因为它做了一个单独的gcc -c main.cpp -o main.o步骤?无论如何,我发现这个命令对案例1非常有用:
.o
g++ -g main.cpp -o foo
foo.dSYM
gcc -c main.cpp -o main.o
$ dsymutil -dump-debug-map main --- triple: 'x86_64-apple-darwin' binary-path: main objects: - filename: /Users/tim/foo/build/CMakeFiles/main.dir/main.cpp.o timestamp: 1485951213 symbols: - { sym: __ZNSt3__111char_traitsIcE11eq_int_typeEii, objAddr: 0x0000000000000D50, binAddr: 0x0000000100001C90, size: 0x00000020 } - { sym: __ZNSt3__111char_traitsIcE6lengthEPKc, objAddr: 0x0000000000000660, binAddr: 0x00000001000015A0, size: 0x00000020 } - { sym: GCC_except_table3, objAddr: 0x0000000000000DBC, binAddr: 0x0000000100001E2C, size: 0x00000000 } - { sym: _main, objAddr: 0x0000000000000000, binAddr: 0x0000000100000F40, size: 0x00000090 } - { sym: __ZNSt3__124__put_character_sequenceIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_PKS4_m, objAddr: 0x00000000000001F0, binAddr: 0x0000000100001130, size: 0x00000470 } - { sym: ___clang_call_terminate, objAddr: 0x0000000000000D40, binAddr: 0x0000000100001C80, size: 0x00000010 } - { sym: GCC_except_table5, objAddr: 0x0000000000000E6C, binAddr: 0x0000000100001EDC, size: 0x00000000 } - { sym: __ZNSt3__116__pad_and_outputIcNS_11char_traitsIcEEEENS_19ostreambuf_iteratorIT_T0_EES6_PKS4_S8_S8_RNS_8ios_baseES4_, objAddr: 0x0000000000000680, binAddr: 0x00000001000015C0, size: 0x000006C0 } - { sym: __ZNSt3__14endlIcNS_11char_traitsIcEEEERNS_13basic_ostreamIT_T0_EES7_, objAddr: 0x00000000000000E0, binAddr: 0x0000000100001020, size: 0x00000110 } - { sym: GCC_except_table2, objAddr: 0x0000000000000D7C, binAddr: 0x0000000100001DEC, size: 0x00000000 } - { sym: __ZNSt3__1lsINS_11char_traitsIcEEEERNS_13basic_ostreamIcT_EES6_PKc, objAddr: 0x0000000000000090, binAddr: 0x0000000100000FD0, size: 0x00000050 } - { sym: __ZNSt3__111char_traitsIcE3eofEv, objAddr: 0x0000000000000D70, binAddr: 0x0000000100001CB0, size: 0x0000000B } ...
jtw3ybtb4#
Apple将调试信息存储在名为 *. dSYM的单独文件中。您可以对这些文件运行dwarfdump,并查看DWARF调试信息条目。
4条答案
按热度按时间jm81lzqq1#
在Mac OS X上,当你链接程序时,有一个决定是让链接器
id
不处理所有的调试信息。调试信息通常是程序可执行文件的大小的10x
,所以让链接器处理所有的调试信息并将其包含在可执行文件的二进制文件中是对链接时间的严重损害。对于迭代开发-编译,链接,编译,链接,调试,编译链接-这是一个真实的的打击。相反,编译器在.s文件中生成
DWARF
调试信息,汇编器在.o文件中输出它,链接器在可执行二进制文件中包含一个“调试Map”,它告诉调试信息用户在链接过程中所有符号的位置。消费者(执行. o文件调试)从可执行文件加载调试Map,并根据需要处理.o文件中的所有DWARF,根据调试Map的指令重新Map符号。
dsymutil
可以被认为是一个调试信息链接器。它执行相同的过程--读取调试Map,从.o文件加载DWARF,重新定位所有地址--然后输出所有DWARF的最终链接地址的一个二进制文件。这就是dSYM包。一旦有了dSYM包,就有了任何dwarf阅读工具(可以处理Mach-O二进制文件)都可以处理的普通旧标准DWARF。
还有一个额外的改进使得所有这些工作都能进行,即Mach-O二进制文件中包含的UUID(v.
otool -hlv
或dwarfdump --uuid
)。这唯一地标识该二进制文件。当dsymutil
创建dSYM时,调试器只会在dSYM和可执行文件有匹配的UUID时将它们关联起来--没有可疑的文件mod时间戳或类似的东西。我们还可以使用UUID来定位二进制文件的dSYM。它们会显示在崩溃报告中,我们包含了一个Spotlight导入器,您可以使用它来搜索它们,例如,如果dSYM位于Spotlight索引位置,则为
mdfind "com_apple_xcode_dsym_uuids == E21A4165-29D5-35DC-D08D-368476F85EE1"
。您甚至可以为您的公司创建一个dSYM存储库,并使用一个程序在给定UUID的情况下检索正确的dSYM-也许是一个小的mysql数据库或类似的东西-所以你在一个随机的可执行文件上运行调试器,你立刻就有了这个可执行文件的所有调试信息。不管怎样,回答你最初的问题:未剥离的二进制文件具有调试Map,.o文件具有DWARF,当运行
dsymutil
时,这些文件被组合以创建dSYM包。如果你想看到调试Map条目,执行
nm -pa executable
,它们都在那里。它们以旧的stabsnlist
记录的形式存在--链接器已经知道如何处理stabs,所以使用它们是最容易的--但是你会看到它是如何工作的,没有太大的麻烦,如果你不确定,也许可以参考一些stabs文档。hkmswyz62#
似乎并没有。
我跟踪了
dsymutil
,它读取了所有的*.o
文件。objdump -h
还列出了其中的所有调试信息。所以看起来这些信息没有被复制到二进制文件中。
关于这一点的一些相关评论也可以在here中找到。
sr4lhrrt3#
OSX似乎有两种方法来放置调试信息:
1.在用于编译的
.o
目标文件中。二进制文件存储对这些文件的引用(通过绝对路径)。1.在一个名为.dSYM的单独捆绑包(目录)中
如果我用苹果的Clang编译,使用
g++ -g main.cpp -o foo
,我得到的包名为foo.dSYM
。然而,如果我使用CMake,我得到的调试信息在对象文件中。我猜是因为它做了一个单独的gcc -c main.cpp -o main.o
步骤?无论如何,我发现这个命令对案例1非常有用:
jtw3ybtb4#
Apple将调试信息存储在名为 *. dSYM的单独文件中。您可以对这些文件运行dwarfdump,并查看DWARF调试信息条目。