【问题标题】:How can I find a proper DWARF symbol for address in a Linux kernel module?如何在 Linux 内核模块中找到合适的 DWARF 符号作为地址?
【发布时间】:2020-12-15 14:54:14
【问题描述】:

我有一个带有 DWARF 调试信息的内核模块。它的所有 ELF 部分都具有零起始地址。 它的 DWARF 信息包含多个重叠的代码和数据符号。它还有许多 DW_AT_low_pc 地址为零的编译单元。

有没有办法在二进制文件中的某个位置找到正确的 DWARF 符号?

【问题讨论】:

  • 不知道我明白你为什么需要这个。模块在运行时链接,0 是正确的值(内核将在加载阶段知道该地址,并可能在链接阶段使用。

标签: linux kernel-module elf dwarf


【解决方案1】:

它还有许多 DW_AT_low_pc 地址为零的编译单元。

内核模块只是一个ET_REL 目标文件。内核知道如何将它链接到它的地址空间中。

DW_AT_low_pcs 全部为 0 的原因是因为有重定位条目会告诉 ld 如何重定位它们iff ld 是为了执行链接。

您可以使用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 中时,您可以看到 重新定位 条目(因为 GDB 知道如何应用它们):

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.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-17
    • 2011-09-09
    • 2013-03-10
    • 2015-04-02
    • 2015-11-27
    • 2014-03-01
    • 2015-02-03
    • 2020-05-06
    相关资源
    最近更新 更多