目标文件的符号table中的局部符号有什么用?
What is the use of local symbols in the symbol table of an object file?
来自问题(Hiding symbol names in library), I thought static functions are removed from an object file's symbol table when compiled with optimization (maybe because compilers assume it is a release build). The below is a slighltly modified source code from (Hiding symbol names in library)和编译目标文件的符号table
// compile with gcc -c -O2 -o file.o file.c
extern int a();
extern int b();
static int f_b1(){
return a();
}
static int f_b3(){
return b();
}
test.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 test.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .comment 0000000000000000 .comment
不过,这样的消失似乎只是因为f_b1和f_b3都没有被使用造成的。显然,如果它们被如下所示的非静态函数调用,它们的符号将重新出现在符号 table 中(即 objdump -t file.o)。
extern int a();
extern int b();
static int __attribute__ ((noinline)) f_b1(){
return a();
}
static int __attribute__ ((noinline)) f_b2(){
return b();
}
void f_b3(){
f_b1();
f_b2();
}
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 test.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l F .text 0000000000000007 f_b1
0000000000000010 l F .text 0000000000000007 f_b2
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 a
0000000000000000 *UND* 0000000000000000 b
0000000000000020 g F .text 0000000000000013 f_b3
因此,默认情况下,即使经过优化,编译器似乎也会将静态函数的符号发送到符号 table 中。那么,这样的局部符号有什么用呢? 在链接阶段是否真的需要它们(我不明白为什么需要它们,因为调用和跳转是以相对于 eip 的方式执行的,不是吗?)?
Are they really required during linking stage
没有。他们只是在那里帮助调试。
您可以使用 objcopy --strip-unneeded test.o test1.o
确认这一点——符号将被删除,但您仍然可以 link test1.o
进入最终的二进制文件,就像使用 [=12] 一样=].
来自问题(Hiding symbol names in library), I thought static functions are removed from an object file's symbol table when compiled with optimization (maybe because compilers assume it is a release build). The below is a slighltly modified source code from (Hiding symbol names in library)和编译目标文件的符号table
// compile with gcc -c -O2 -o file.o file.c
extern int a();
extern int b();
static int f_b1(){
return a();
}
static int f_b3(){
return b();
}
test.o: file format elf64-x86-64
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 test.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .comment 0000000000000000 .comment
不过,这样的消失似乎只是因为f_b1和f_b3都没有被使用造成的。显然,如果它们被如下所示的非静态函数调用,它们的符号将重新出现在符号 table 中(即 objdump -t file.o)。
extern int a();
extern int b();
static int __attribute__ ((noinline)) f_b1(){
return a();
}
static int __attribute__ ((noinline)) f_b2(){
return b();
}
void f_b3(){
f_b1();
f_b2();
}
SYMBOL TABLE:
0000000000000000 l df *ABS* 0000000000000000 test.c
0000000000000000 l d .text 0000000000000000 .text
0000000000000000 l d .data 0000000000000000 .data
0000000000000000 l d .bss 0000000000000000 .bss
0000000000000000 l F .text 0000000000000007 f_b1
0000000000000010 l F .text 0000000000000007 f_b2
0000000000000000 l d .note.GNU-stack 0000000000000000 .note.GNU-stack
0000000000000000 l d .eh_frame 0000000000000000 .eh_frame
0000000000000000 l d .comment 0000000000000000 .comment
0000000000000000 *UND* 0000000000000000 _GLOBAL_OFFSET_TABLE_
0000000000000000 *UND* 0000000000000000 a
0000000000000000 *UND* 0000000000000000 b
0000000000000020 g F .text 0000000000000013 f_b3
因此,默认情况下,即使经过优化,编译器似乎也会将静态函数的符号发送到符号 table 中。那么,这样的局部符号有什么用呢? 在链接阶段是否真的需要它们(我不明白为什么需要它们,因为调用和跳转是以相对于 eip 的方式执行的,不是吗?)?
Are they really required during linking stage
没有。他们只是在那里帮助调试。
您可以使用 objcopy --strip-unneeded test.o test1.o
确认这一点——符号将被删除,但您仍然可以 link test1.o
进入最终的二进制文件,就像使用 [=12] 一样=].