1

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?

Denis
  • 13
  • 2
  • Not sure I understand why you need this. Modules are linked at runtime and 0 is a correct value (kernel will know that address during loading stage and may use at linking stage. – 0andriy Dec 15 '20 at 19:54

1 Answers1

1

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_pcs 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.
Employed Russian
  • 199,314
  • 34
  • 295
  • 362