如何在 Linux 内核模块中为地址找到合适的 DWARF 符号?
How can I find a proper DWARF symbol for address in a Linux kernel module?
我有一个带有 DWARF 调试信息的内核模块。它的所有 ELF 部分都具有零起始地址。
它的 DWARF 信息包含多个重叠的代码和数据符号。它还具有许多零 DW_AT_low_pc 地址的编译单元。
有没有办法为二进制文件中的特定位置找到正确的 DWARF 符号?
It also has many compilation units with zero DW_AT_low_pc address.
一个内核模块就是一个ET_REL
目标文件。内核知道如何将它 link 放入它的地址 space.
之所以 DW_AT_low_pc
全部为 0 是因为有重定位条目会告诉 ld
如何重定位它们 iff ld
是执行 link.
您可以使用 readelf -Wr module.ko
检查这些条目,但让 GDB 这样做更容易。
示例:
// f.c
int foo(int x)
{
return x;
}
int bar(int x)
{
return foo(x);
}
gcc -c -g f.c -ffunction-sections
结果 f.o
的所有内容都为 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
但是当加载到 GDB 中时,您可以看到 relocated 条目(因为 GDB 知道如何应用它们):
gdb -q f.o
Reading symbols from f.o...
(gdb) p &foo
= (int (*)(int)) 0x0 <foo>
(gdb) p &bar
= (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 [=12=]x8,%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.
我有一个带有 DWARF 调试信息的内核模块。它的所有 ELF 部分都具有零起始地址。 它的 DWARF 信息包含多个重叠的代码和数据符号。它还具有许多零 DW_AT_low_pc 地址的编译单元。
有没有办法为二进制文件中的特定位置找到正确的 DWARF 符号?
It also has many compilation units with zero DW_AT_low_pc address.
一个内核模块就是一个ET_REL
目标文件。内核知道如何将它 link 放入它的地址 space.
之所以 DW_AT_low_pc
全部为 0 是因为有重定位条目会告诉 ld
如何重定位它们 iff ld
是执行 link.
您可以使用 readelf -Wr module.ko
检查这些条目,但让 GDB 这样做更容易。
示例:
// f.c
int foo(int x)
{
return x;
}
int bar(int x)
{
return foo(x);
}
gcc -c -g f.c -ffunction-sections
结果 f.o
的所有内容都为 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
但是当加载到 GDB 中时,您可以看到 relocated 条目(因为 GDB 知道如何应用它们):
gdb -q f.o
Reading symbols from f.o...
(gdb) p &foo
= (int (*)(int)) 0x0 <foo>
(gdb) p &bar
= (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 [=12=]x8,%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.