I have a kernel module with DWARF debug info. All its ELF sections have zero start addresses. Its DWARF info contains multiple overlapping code and data symbols. It also has many compilation units with zero DW_AT_low_pc address.
Is there a way to find the right DWARF symbol for a certain location in the binary file?
It also has many compilation units with zero DW_AT_low_pc address.
A kernel module is just a ET_REL
object file. The kernel knows how to link it in into its address space.
The reason DW_AT_low_pc
s are all 0s is because there are relocation entries that would have told the ld
how to relocate them iff ld
was to perform the link.
You could examine these entries with readelf -Wr module.ko
, but it's much easier to ask GDB to do so.
Example:
// f.c
int foo(int x)
{
return x;
}
int bar(int x)
{
return foo(x);
}
gcc -c -g f.c -ffunction-sections
Resulting f.o
has everything at 0:
nm f.o
0000000000000000 T bar
0000000000000000 T foo
readelf -wi f.o | grep low_pc
<1d> DW_AT_low_pc : 0x0
<35> DW_AT_low_pc : 0x0
<6c> DW_AT_low_pc : 0x0
But when loaded into GDB, you can see relocated entries (because GDB knows how to apply them):
gdb -q f.o
Reading symbols from f.o...
(gdb) p &foo
$1 = (int (*)(int)) 0x0 <foo>
(gdb) p &bar
$2 = (int (*)(int)) 0xc <bar> <<=== not 0
(gdb) disas/s foo
Dump of assembler code for function foo:
f.c:
2 {
0x0000000000000000 <+0>: push %rbp
0x0000000000000001 <+1>: mov %rsp,%rbp
0x0000000000000004 <+4>: mov %edi,-0x4(%rbp)
3 return x;
0x0000000000000007 <+7>: mov -0x4(%rbp),%eax
4 }
0x000000000000000a <+10>: pop %rbp
0x000000000000000b <+11>: retq
End of assembler dump.
(gdb) disas/s bar
Dump of assembler code for function bar:
f.c:
7 {
0x000000000000000c <+0>: push %rbp
0x000000000000000d <+1>: mov %rsp,%rbp
0x0000000000000010 <+4>: sub $0x8,%rsp
0x0000000000000014 <+8>: mov %edi,-0x4(%rbp)
8 return foo(x); <<=== correct line
0x0000000000000017 <+11>: mov -0x4(%rbp),%eax
0x000000000000001a <+14>: mov %eax,%edi
0x000000000000001c <+16>: callq 0x21 <bar+21>
9 }
0x0000000000000021 <+21>: leaveq
0x0000000000000022 <+22>: retq
End of assembler dump.