简体   繁体   English

Linux 内核函数 memblock_alloc_range_nid 不在地址空间中

[英]Linux Kernel function memblock_alloc_range_nid is not presented in the address space

I'm trying to debug physical memory allocation to understand what part of the Linux Kernel use memblock_alloc_range_nid on x86-64 and how.我正在尝试调试物理内存分配以了解 Linux 内核的哪些部分在x86-64上使用memblock_alloc_range_nid以及如何使用。

I'm running the latest Linux Kernel 5.19-rc2 built from upstream with Ubuntu 20.04 inside QEMU.我正在使用 QEMU 中的Ubuntu 20.04运行从上游构建的最新Linux Kernel 5.19-rc2 The problem is it's not possible to access memory address the function memblock_alloc_range_nid is located at.问题是无法访问函数memblock_alloc_range_nid所在的内存地址。 While other Kernel functions can be easily disassembled.而其他内核功能可以很容易地反汇编。

Here is what I have in my gdb connected to the QEMU VM:这是我的gdb中连接到 QEMU VM 的内容:

(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.

What's wrong with the function memblock_alloc_range_nid ?函数memblock_alloc_range_nid有什么问题? Why is it not possible to access its address?为什么无法访问其地址? It seems all the function frommemblock.c cannot be accessed.似乎无法访问memblock.c中的所有功能。

As Margaret and Roi have noted in the above comments, memblock_alloc_range_nid() is annotated with __init .正如MargaretRoi在上述评论中所指出的, memblock_alloc_range_nid()使用__init进行注释。 Functions annotated with __init , __head and similar macros are only needed during kernel initialization right after boot.使用__init__head和类似宏注释的函数仅在启动后内核初始化期间才需要。 After the kernel has finished initializing things, the special memory section containing all those functions is unmapped from memory since they are not needed anymore.在内核完成初始化之后,包含所有这些函数的特殊内存部分将从内存中取消映射,因为不再需要它们。

If you want to debug any such function, you will have to break very early, for example at start_kernel() , then you can inspect the function or set a breakpoint and continue execution to hit it.如果要调试任何此类函数,则必须尽早中断,例如在start_kernel()处,然后您可以检查该函数或设置断点并continue执行以命中它。

Important: add -S (uppercase) to your QEMU command line options to make it stop and wait for the debugger before starting the kernel, and start the kernel with KASLR disabled using -append "nokaslr" (or adding nokaslr if you are already specifying -append ).重要提示:在 QEMU 命令行选项中添加-S (大写)以使其在启动内核之前停止并等待调试器,并在禁用 KASLR 的情况下使用-append "nokaslr"启动内核(如果您已经指定,则添加nokaslr - -append )。

The following GDB script should be what you need:以下 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

Launch gdb -x script.gdb (after starting QEMU), and when you hit the start_kernel breakpoint, you can add another one for memblock_alloc_range_nid , then 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
   ...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM