c - Linux 内核函数 memblock_alloc_range_nid 未出现在地址空间中

标签 c linux-kernel x86 gdb qemu

我正在尝试调试物理内存分配以了解 Linux 内核的哪一部分使用 memblock_alloc_range_nidx86-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无法访问。

最佳答案

作为MargaretRoi在上面的评论中已经注意到,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/

相关文章:

c - 在处理 .wav 文件时我应该使用哪种 fopen() 模式?

c - 使用 C,如何访问与另一个 C 程序相同的内存块?

c - 信号量意外设置

.net - 为什么 .net 程序集对于不同的体系结构会有所不同?

assembly - 为什么 `call dword 0x12345678` 会编译成 [66,E8,72,56,34,12]?

c++ - 如何使用 DetourAttachEx 创建蹦床函数? (有MS绕路)

C stat 结构没有 st_ctime 字段,只有 st_ctim

c - 错误 : expected ')' before

linux - 调度程序中的 sched_feat 宏是什么意思

c - 如何使用自己的函数覆盖系统调用表条目?