On IRC, I mentioned to Mark some bias issues I was having with values
from dwfl_module_getsym, and I promised a smaller reproducer than using
systemtap, so here's my attempt to recreate it with test code that
already exists in elfutils.
The problem I'm having surrounds gnu_debugdata, and tests/dwflsyms
already covers this scenario with testfilebazmdb and testfilebazmin. So
let's experiment with prelinking these.
Note, I extracted all testfilebaz* in my working directory, mainly to
make sure the .debug was also available. I'm also grepping output to
reduce how long this email gets. :)
First testfilebazmdb (dynsym + gnu_debugdata + .debug):
$ ./dwflsyms -e testfilebazmdb | grep -w FUNC | grep -wE
'main|foo|bar'
45: FUNC LOCAL foo (20) 0x814
58: FUNC GLOBAL bar (44) 0x828
70: FUNC GLOBAL main (35) 0x7f0
$ /usr/sbin/prelink -N testfilebazmdb
$ ./dwflsyms -e testfilebazmdb | grep -w FUNC | grep -wE 'main|foo|bar'
45: FUNC LOCAL foo (20) 0x3005800814
58: FUNC GLOBAL bar (44) 0x3005800828
70: FUNC GLOBAL main (35) 0x30058007f0
$ /usr/sbin/prelink -u testfilebazmdb
$ /usr/sbin/prelink -r 0x70000000 testfilebazmdb
$ ./dwflsyms -e testfilebazmdb | grep -w FUNC | grep -wE 'main|foo|bar'
45: FUNC LOCAL foo (20) 0x70000814
58: FUNC GLOBAL bar (44) 0x70000828
70: FUNC GLOBAL main (35) 0x700007f0
This all looks fine; all three functions move around together.
Now testfilebazmin (dynsym + gnu_debugdata)
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE
'main|foo|bar'
6: FUNC LOCAL foo (18) 0x400498
42: FUNC GLOBAL main (35) 0x7f0
45: FUNC GLOBAL bar (44) 0x4004aa
Already a bad start - foo/bar look like symbols that would belong in
ET_EXEC (which indeed the embedded gnu_debugdata really is). I would
not expect that to show up in the main file getsym list, even though
run-dwflsyms.sh is asserting this output.
$ /usr/sbin/prelink -N testfilebazmin
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE 'main|foo|bar'
12: FUNC GLOBAL main (35) 0x30058007f0
Here we completely lost foo/bar!
$ /usr/sbin/prelink -u testfilebazmin
$ /usr/sbin/prelink -r 0x70000000 testfilebazmin
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE 'main|foo|bar'
6: FUNC LOCAL foo (18) 0x400498
42: FUNC GLOBAL main (35) 0x700007f0
45: FUNC GLOBAL bar (44) 0x4004aa
Ok, foo/bar came back but still refuse to relocate with main.
I would expect testfilebazmdb and testfilebazmin to behave the same way.
Even if the latter's symbol tables are less complete, the symbols that
are presented ought to be consistent in their base offset, so any can be
used with dwfl_module_relocate_address.
The ET_EXEC gnu_debugdata in both bazmdb and bazmin is suspicious. I
followed your directions to generate all these testfilebaz* on Fedora
19, and I got ET_DYN gnu_debugdata. The symbols are also the same size
and location in my bazmdb and bazmin, whereas you can see above the test
files in elfutils.git are not.
Repeating my prelink sequence on these new binaries, bazmdb still looks
good, and now bazmin looks like this:
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE
'main|foo|bar'
8: FUNC LOCAL foo (20) 0x75c
47: FUNC GLOBAL bar (40) 0x770
51: FUNC GLOBAL main (35) 0x738
$ /usr/sbin/prelink -N testfilebazmin
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE 'main|foo|bar'
8: FUNC LOCAL foo (20) 0x300580075c
47: FUNC GLOBAL bar (40) 0x3005800770
51: FUNC GLOBAL main (35) 0x3005800738
$ /usr/sbin/prelink -u testfilebazmin
$ /usr/sbin/prelink -r 0x70000000 testfilebazmin
$ ./dwflsyms -e testfilebazmin | grep -w FUNC | grep -wE 'main|foo|bar'
8: FUNC LOCAL foo (20) 0x75c
47: FUNC GLOBAL bar (40) 0x770
51: FUNC GLOBAL main (35) 0x738
Normal prelink is better here, but now prelink -r didn't actually appear
to move any of foo, bar, or main!?! However, this grep is too tight,
because some a few symbols did report moved, like _end. I'll end with
that full output:
$ ./dwflsyms -e testfilebazmin
0: NOTYPE LOCAL (0) 0
1: SECTION LOCAL (0) 0x70000238
2: FUNC LOCAL deregister_tm_clones (0) 0x650
3: FUNC LOCAL register_tm_clones (0) 0x680
4: FUNC LOCAL __do_global_dtors_aux (0) 0x6c0
5: OBJECT LOCAL __do_global_dtors_aux_fini_array_entry (0) 0x200df0
6: FUNC LOCAL frame_dummy (0) 0x700
7: OBJECT LOCAL __frame_dummy_init_array_entry (0) 0x200de8
8: FUNC LOCAL foo (20) 0x75c
9: NOTYPE LOCAL __init_array_end (0) 0x200df0
10: NOTYPE LOCAL __init_array_start (0) 0x200de8
11: SECTION LOCAL (0) 0x238
12: SECTION LOCAL (0) 0x254
13: SECTION LOCAL (0) 0x274
14: SECTION LOCAL (0) 0x298
15: SECTION LOCAL (0) 0x2c8
16: SECTION LOCAL (0) 0x3d0
17: SECTION LOCAL (0) 0x47a
18: SECTION LOCAL (0) 0x490
19: SECTION LOCAL (0) 0x4b0
20: SECTION LOCAL (0) 0x570
21: SECTION LOCAL (0) 0x5b8
22: SECTION LOCAL (0) 0x5e0
23: SECTION LOCAL (0) 0x620
24: SECTION LOCAL (0) 0x814
25: SECTION LOCAL (0) 0x820
26: SECTION LOCAL (0) 0x824
27: SECTION LOCAL (0) 0x868
28: SECTION LOCAL (0) 0x200de8
29: SECTION LOCAL (0) 0x200df0
30: SECTION LOCAL (0) 0x200df8
31: SECTION LOCAL (0) 0x200e00
32: SECTION LOCAL (0) 0x200e08
33: SECTION LOCAL (0) 0x200fd8
34: SECTION LOCAL (0) 0x201000
35: SECTION LOCAL (0) 0x201030
36: SECTION LOCAL (0) 0x20103c
37: NOTYPE WEAK _ITM_deregisterTMCloneTable (0) 0
38: FUNC GLOBAL __libc_start_main (0) 0
39: NOTYPE WEAK __gmon_start__ (0) 0
40: NOTYPE WEAK _Jv_RegisterClasses (0) 0
41: NOTYPE WEAK _ITM_registerTMCloneTable (0) 0
42: FUNC WEAK __cxa_finalize (0) 0
43: NOTYPE GLOBAL _edata (0) 0x7020103c
44: NOTYPE GLOBAL _end (0) 0x70201040
45: NOTYPE GLOBAL __bss_start (0) 0x7020103c
46: FUNC GLOBAL __libc_csu_fini (2) 0x810
47: FUNC GLOBAL bar (40) 0x770
48: FUNC GLOBAL _fini (0) 0x814
49: FUNC GLOBAL __libc_csu_init (101) 0x7a0
50: FUNC GLOBAL _start (0) 0x620
51: FUNC GLOBAL main (35) 0x738
52: FUNC GLOBAL _init (0) 0x5b8