【发布时间】:2020-03-19 01:55:20
【问题描述】:
我了解符号表是由编译器创建以帮助其处理的。 当它们被链接在一起时,它们存在于每个目标文件中。
假设:
void test(void){
//
}
void main(){
return 0;
}
用 gcc 编译上面并运行nm a.out 显示:
0000000100000fa0 T _main
0000000100000f90 T _test
为什么仍然需要这些符号?为什么链接器在完成后不删除它们?对黑客阅读源代码而言,它们不是潜在的安全风险吗?
编辑
这就是你调试发布二进制文件的意思吗(编译时没有-g)?
假设:
int test2(){
int *p = (int*) 0x123;
return *p;
}
int test1(){
return test2();
}
int main(){
return test1();
}
test2 上的哪些段错误。正在做gdb ./a.out > where 显示:
(gdb) where
#0 0x000055555555460a in test2 ()
#1 0x000055555555461c in test1 ()
#2 0x000055555555462c in main ()
但是剥离a.out 并做同样的事情:
(gdb) where
#0 0x000055555555460a in ?? ()
#1 0x000055555555461c in ?? ()
#2 0x000055555555462c in ?? ()
这就是keeping symbol tables for debugging release builds 的意思吗?这是正常的做法吗?是否使用了其他工具?
【问题讨论】:
-
你显然从未使用过调试器。
-
可能比你用得更多。
gcc -g用于 gdb。没有-g的 gcc 仍然有符号表。 -
-g将更多调试信息添加到图像中。但这是符号提供的额外内容。如果没有符号,除非您知道加载地址,否则您将无法在test函数上设置断点。试试看:在可执行文件上运行strip,然后尝试在任何函数上设置断点。 -
@Josh:当然,没有理由调试发布版本,因为它们从来没有错误并且总是与调试版本完全相同。
-
@Josh 您的船舶版本是为您的客户构建的,对吗?那么,如果您交付的程序崩溃并且您的客户有核心转储,那么您如何理解没有符号的情况?您不必仅仅因为链接器将符号提供给您就发送符号。
标签: c linker symbol-table