我正在尝试调试物理内存分配以了解 Linux 内核的哪一部分使用 memblock_alloc_range_nid在 x86-64
上以及如何实现。
我正在运行最新的 Linux Kernel 5.19-rc2
,它是在 QEMU 中使用 Ubuntu 20.04
从上游构建的。问题是无法访问函数 memblock_alloc_range_nid
所在的内存地址。而其他内核功能可以轻松反汇编。
这是我连接到 QEMU VM 的 gdb
中的内容:
(gdb) disas memblock_alloc_range_nid
Cannot access memory at address 0xffffffff831a05d1
(gdb) disas native_safe_halt
Dump of assembler code for function native_safe_halt:
#...
End of assembler dump.
函数 memblock_alloc_range_nid
有什么问题?为什么无法访问其地址?似乎所有功能都来自memblock.c
无法访问。
最佳答案
作为Margaret和 Roi在上面的评论中已经注意到,memblock_alloc_range_nid()
注释为 __init
.用 __init
注释的函数, __head
并且类似的宏仅在启动后的内核初始化期间才需要。内核完成初始化后,包含所有这些函数的特殊内存部分将从内存中取消映射,因为不再需要它们。
如果你想调试任何这样的函数,你必须很早就中断,例如在 start_kernel()
, 然后你可以检查函数或设置断点和 continue
执行击中它。
重要:添加 -S
(大写)到您的 QEMU 命令行选项,使其在启动内核之前停止并等待调试器,并使用 -append "nokaslr"
在禁用 KASLR 的情况下启动内核(或者添加 nokaslr
如果您已经指定了 -append
)。
以下 GDB 脚本应该是您所需要的:
$ cat script.gdb
directory /path/to/kernel-source-dir
file /path/to/kernel-source-dir/vmlinux
target remote localhost:1234
break start_kernel
continue
启动 gdb -x script.gdb
(在启动 QEMU 之后),当你点击 start_kernel
时断点,您可以为 memblock_alloc_range_nid
添加另一个断点, 然后 continue
:
0x000000000000fff0 in exception_stacks ()
Breakpoint 1 at 0xffffffff82fbab4c
Breakpoint 1, 0xffffffff82fbab4c in start_kernel ()
(gdb) b memblock_alloc_range_nid
Breakpoint 2 at 0xffffffff82fe2879
(gdb) c
Continuing.
Breakpoint 2, 0xffffffff82fe2879 in memblock_alloc_range_nid ()
(gdb) disassemble
Dump of assembler code for function memblock_alloc_range_nid:
=> 0xffffffff82fe2879 <+0>: push r15
0xffffffff82fe287b <+2>: mov r15,rcx
0xffffffff82fe287e <+5>: push r14
0xffffffff82fe2880 <+7>: mov r14,rdx
0xffffffff82fe2883 <+10>: push r13
0xffffffff82fe2885 <+12>: mov r13d,r9
...
关于c - Linux 内核函数 memblock_alloc_range_nid 未出现在地址空间中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72722745/