QEMU+GDB调试Linux 5.19时memblock_alloc_range_nid地址无法访问
故障根因
该问题和函数本身逻辑异常无关,本质是内核初始化代码段在系统启动完成后被回收导致的:
memblock_alloc_range_nid以及memblock.c内的绝大多数memblock相关函数,都被__init宏修饰,属于内核启动早期专用代码。这类代码仅在内存管理子系统初始化完成前的启动阶段运行,当内核完成全部初始化流程、进入用户态运行阶段后,这部分代码占用的内存会被内核直接释放,并入伙伴分配器作为通用内存供其他模块使用。- 你当前调试时,虚拟机已经正常运行
Ubuntu 20.04用户态环境,远超内核初始化阶段,原存放memblock_alloc_range_nid指令的内存已经被回收覆写,gdb访问的0xffffffff831a05d1地址已经不再保留原函数的机器码,因此会报内存无法访问的错误。 native_safe_halt可以正常反汇编,是因为该函数属于内核运行时全程需要调用的核心功能,没有被放入初始化段,启动完成后对应的代码段内存会被永久保留,因此可以正常访问。
可行调试方案
如果需要跟踪memblock_alloc_range_nid的调用逻辑,不能等系统启动完成后再操作,需要在QEMU启动内核的早期阶段介入调试:
- 连接gdb后先在
start_kernel函数位置下断点,系统触发该断点时仍处于内核初始化流程中,初始化段内存尚未被回收,此时即可正常对memblock_alloc_range_nid执行反汇编、下断点操作,完整跟踪所有调用链路。 - 如果仅需要梳理所有调用该函数的模块,也可以直接通过内核源码的静态索引检索所有调用点,结合早期启动阶段的断点验证调用逻辑即可。
内容的提问来源于stack exchange,提问作者Some Name
相关产品推荐
相关产品推荐

