代码:
//test.c
#include <stdio.h>
int v_flag = 0xCACA;
void main(int argc, char* argv[]){
printf("v_flag = %d, &v_flag=%p \n", v_flag, &v_flag);
v_flag++;
printf("v_flag = %d\n", v_flag);
}
编译:
$ gcc -fPIC -o test test.c
运行:(不重要)
$ ./test v_flag = 51914, &v_flag=0x601034 v_flag = 51915
读取符号表:
$ gcc --version gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-8) ... $ ld --version GNU ld version 2.23.52.0.1-16.el7 20130226 ... $ readelf -s test Symbol table '.dynsym' contains 4 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ Symbol table '.symtab' contains 65 entries: Num: Value Size Type Bind Vis Ndx Name ... 58: 0000000000601048 0 NOTYPE GLOBAL DEFAULT 25 _end 59: 0000000000400450 0 FUNC GLOBAL DEFAULT 13 _start 60: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 __bss_start 61: 0000000000400514 89 FUNC GLOBAL DEFAULT 13 main 62: 0000000000601034 4 OBJECT GLOBAL DEFAULT 24 v_flag ...
问题1 :为什么全局变量 v_flag 出现在 symtab 中,而不出现在 dynsym 中? (注意:禁用优化“-O0”没有帮助)
关注问题1,添加“ -rdynamic ”标志将使 v_flag (以及其他人)出现在 dynsym 中:
$ gcc -rdynamic -o test test.c $ readelf -s test Symbol table '.dynsym' contains 18 entries: Num: Value Size Type Bind Vis Ndx Name 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2) 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2) 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ ... 11: 0000000000400670 0 FUNC GLOBAL DEFAULT 13 _start 12: 0000000000601038 0 NOTYPE GLOBAL DEFAULT 25 __bss_start 13: 0000000000400734 89 FUNC GLOBAL DEFAULT 13 main 14: 0000000000400600 0 FUNC GLOBAL DEFAULT 11 _init 15: 0000000000400800 2 FUNC GLOBAL DEFAULT 13 __libc_csu_fini 16: 0000000000400848 0 FUNC GLOBAL DEFAULT 14 _fini 17: 0000000000601034 4 OBJECT GLOBAL DEFAULT 24 v_flag Symbol table '.symtab' contains 65 entries: ...
然而,根据手册页
-rdynamic Pass the flag -export-dynamic to the ELF linker, on targets that support it. This instructs the linker to add all symbols, not only used ones, to the dynamic symbol table.
因此,问题2 ,我们可以说 v_flag 未使用(因此它不会出现在 dynsym )?如果是这样,为什么?
更新1:
这个问题没有出现在ld版本2.20。*中(感谢Konstantin Vladimirov指出这一点)。
答案 0 :(得分:1)
首先你应该意识到,即使使用rdynamic
,你在这里做的事情也很尴尬 - 将依赖于位置的v_flag
导出到动态加载器特定的dynsym
部分。
回答你的问题 - 因为它未被使用而被删除。 它未被使用,因为它无法在任何合理的动态环境中使用。
我认为你真正想要的是编译一个与位置无关的代码:
gcc -o test test.c -fPIC
现在没有任何rdynamic黑客,你确实有:
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
2: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
3: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
4: 0000000000601020 4 OBJECT GLOBAL DEFAULT 25 v_flag
我建议你阅读一些关于编写共享库的文档。 This one is my favorite
汇编:
.globl v_flag
.data
.align 4
.type v_flag, @object
.size v_flag, 4
v_flag:
.long 51914
测试:GCC 4.4.3,GCC 4.7.2,GCC 4.8.2,GCC 4.9.2,链接器ld 2.20.1
答案 1 :(得分:0)
由于无法发表评论,因此不得不在此处写下。
GNU ld version 2.20.51.0.2-5.36.el6 20100205
中发生了相同的行为(即,dynsym表中未显示v_flag)。
因此,我想编辑出有问题的更新,因为并非所有2.20。*都适用。
因此,目前唯一的方法是使用-rdynamic,如果还有其他方法,请有人提供答案,因为-rdynamic就像是黑客。
我也看到了没有rdynamic并且ld-version> 2.23有效的情况,但是我看不出原因或无法重现该原因。