当没有加载调试符号时,gdb如何解释`main`?

时间:2011-05-09 01:20:54

标签: c gdb

<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /root/ctest/printf...(no debugging symbols found)...done.
(gdb) disas main
Dump of assembler code for function main:
0x0000000000400498 <main+0>:    push   %rbp
0x0000000000400499 <main+1>:    mov    %rsp,%rbp
0x000000000040049c <main+4>:    sub    $0x10,%rsp

如果没有加载调试符号,gdb如何解释main

2 个答案:

答案 0 :(得分:2)

GDB没有“解释”main

如果你的问题是“GDB如何知道main是哪里”,答案是:“因为它的地址在符号表中”(参见nm /root/ctest/printf的输出)。在UNIX上(与Windows不同),不需要调试符号在可执行文件(或共享库)中包含函数和全局变量名称 - 默认情况下它们保留(以使调试更容易)。如果您想要隐藏main,可以运行strip printf将其从可执行文件中删除(以及所有其他符号)。

对于您的第二个问题,main没有受损,因为它有extern "C"个关联。它必须具有该链接,因此可以从程序集调用它(它由C运行时启动调用,通常为crt1.o)。

答案 1 :(得分:0)

main不是调试符号,因此不会被剥离。它具有外部链接,因此除非显式的strip或link命令将其删除,否则它将被保留。它没有被破坏,因为在大多数平台上,C ABI中没有名称错误(除了可能附加下划线或类似名称)。

链接器和其他工具能够确定哪些符号是调试符号,哪些符号是extern或private等,因为它们在符号表中的标记方式不同。例如,在Mac OS X上,我们可能会看到如下内容:

                 U _constantFromAnotherModule
0000000000000018 T _externFunction
0000000000000410 s _privateInt
0000000000000000 t _staticFunction

中间列中的不同字母,在符号名称之前,表示不同类型的链接,并且工具对它们的处理方式不同。

即使符号损坏,工具通常也知道如何撤消修改,因此调试器应该能够在符号表中找到一个函数名,即使它已经被修改了,所以因为它是由与调试器兼容的工具构建的。除此之外,C ++中的main( )具有C链接,并且遵循平台的C ABI,因此通常不会被破坏。