Reputation: 83
Code:
//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);
}
Compile:
$ gcc -fPIC -o test test.c
Run: (not important)
$ ./test v_flag = 51914, &v_flag=0x601034 v_flag = 51915
Read symbol tables:
$ 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 ...
Question 1: Why the global variable v_flag appears in symtab, but not in dynsym? (note: disable optimizations "-O0" does not help)
Following up Question 1, adding "-rdynamic" flag will make v_flag (and also others) appear in 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: ...
However, according to the man page
-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.
Hence, question 2, can we say that v_flag is unused (hence it does not appear in dynsym)? If so, why?
Update 1:
This issue does not show up in ld version 2.20.* (Thank Konstantin Vladimirov for pointing out this).
Upvotes: 2
Views: 4788
Reputation: 25
Was not able to comment so had to write it here.
The same behavior(i.e doesn't show v_flag in dynsym table) happens in GNU ld version 2.20.51.0.2-5.36.el6 20100205
.
So I guess edit out the Update in question as not all 2.20.* works.
So for now only way is to use -rdynamic, someone please add an answer if there is some other way, because -rdynamic feels like a hack.
Also I have seen cases where without rdynamic and also ld-version > 2.23 works, but I am not able to see the reason or reproduce it on why that works.
Upvotes: 0
Reputation: 7009
First you should realize, that even with rdynamic
, you are doing here something really awkward -- exporting position-dependent v_flag
to dynamic loader specific dynsym
section.
Answering your questions -- it is dropped because it is unused. And it is unused because it can not be used in any sensible dynamic context.
I think what you do really want -- is to compile a code to be positional independent:
gcc -o test test.c -fPIC
Now without any rdynamic hacks, you do have:
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
I suggest you to read some docs on writing shared libraries. This one is my favorite.
In assembly:
.globl v_flag
.data
.align 4
.type v_flag, @object
.size v_flag, 4
v_flag:
.long 51914
Tested: GCC 4.4.3, GCC 4.7.2, GCC 4.8.2, GCC 4.9.2, linker ld 2.20.1
Upvotes: 2