使用gdb调试内核

1. 使用gdb调试内核

内核配置需要添加编译信息。

# 开启kernel debug info
Kernel hacking  ---> 
    [*] Kernel debugging
    Compile-time checks and compiler options  --->
        [*] Compile the kernel with debug info
        [*]   Provide GDB scripts for kernel debuggin
# 关闭地址随机化
kernel features ---->
    [] Randomize the address of the kernel image (KASLR)

建议关闭地址随机化,否则会出现gdb中无法在断点处停下来的情况(尤其是qemu中)。可以参考:https://blog.csdn.net/gatieme/article/details/104266966

在目标板上开启gdbserver模式(虚拟soc中加上gdb调试的选项);在host上启动gdb客户端后连接虚拟soc提供的gdb服务(终端不会有输出),命令如下:

# 启动gdb,工具链中gdb的路径,并读取符号表
# vmlinux相当于elf文件,具有符号表。Image文件相当于bin文件。
aarch64-linux-gnu-gdb ./linux-5.18/vmlinux
# 连接gdb server, 7777 为端口号,
tar remote localhost:7777
# 设置断点
b start_kernel
# 运行
c

在目标板的串口则会有对应的输出信息。

2. 使用gdb扩展

内核通过python脚本定义了一组gdb命令,可方便其对内核的调试,如通过该脚本可以打印dmesg,percpu变量,通过pid打印其对应的task_struct结构体等。

内核编译时要除了4.1的配置,还需要开启CONFIG_GDB_SCRIPTS支持。

> Kernel hacking > Compile-time checks and compiler options
 	 [*]   Provide GDB scripts for kernel debugging
 # 同时要保证内核地址随机化关闭,Reduce debugging information 关闭
 	[ ]   Reduce debugging information 

编译后在linux内核主目录(vmlinux同级目录)下会生成文件:vmlinux-gdb.py。在gdb中可以读取该文件。

# 启动gdb,工具链中gdb的路径,并读取符号表
# vmlinux相当于elf文件,具有符号表。Image文件相当于bin文件。
aarch64-linux-gnu-gdb ./linux-5.18/vmlinux

# 设置路径
add-auto-load-safe-path ./linux-5.10.142
# 加载vmlinux-gdb.py
source ./vmlinux-gdb.py
# 连接gdb server, 77777 为端口号,目标板的gdbserver的端口号对应
tar remote localhost:7777
# 通过lx-symbols命令加载内核和模块的符号表
lx-symbols
# 就可以使用扩展指令了
# 查看支持的扩展指令
apropos lx
# 设置断点
b start_kernel
# 运行
c

使用’apropos lx’查看常用的支持的扩展指令:

function lx_clk_core_lookup -- Find struct clk_core by name
function lx_current         -- Return current task.
function lx_device_find_by_bus_name   -- Find struct device by bus and name (both strings)
function lx_device_find_by_class_name -- Find struct device by class and name (both strings)
function lx_module   -- Find module by name and return the module variable.
function lx_per_cpu  -- Return per-cpu variable.
function lx_rb_first -- Lookup and return a node from an RBTree
function lx_rb_last  -- Lookup and return a node from an RBTree.
function lx_rb_next  -- Lookup and return a node from an RBTree.
function lx_rb_prev  -- Lookup and return a node from an RBTree.
function lx_task_by_pid -- Find Linux task by PID and return the task_struct variable.
function lx_thread_info -- Calculate Linux thread_info from task variable.
function lx_thread_info_by_pid -- Calculate Linux thread_info from task variable found by pid
lx-clk-summary -- Print clk tree summary
lx-cmdline --  Report the Linux Commandline used in the current kernel.
lx-configdump -- Output kernel config to the filename specified as the command
lx-cpus -- List CPU status arrays
lx-device-list-bus -- Print devices on a bus (or all buses if not specified)
lx-device-list-class -- Print devices in a class (or all classes if not specified)
lx-device-list-tree -- Print a device and its children recursively
lx-dmesg -- Print Linux kernel log buffer.
lx-fdtdump -- Output Flattened Device Tree header and dump FDT blob to the filename
lx-genpd-summary -- Print genpd summary
lx-iomem -- Identify the IO memory resource locations defined by the kernel
lx-ioports -- Identify the IO port resource locations defined by the kernel
lx-list-check -- Verify a list consistency
lx-lsmod -- List currently loaded modules.
lx-mounts -- Report the VFS mounts of the current process namespace.
lx-ps -- Dump Linux tasks.
lx-symbols -- (Re-)load symbols of Linux kernel and currently loaded modules.
lx-timerlist -- Print /proc/timer_list
lx-version --  Report the Linux Version of the current kernel.

你可能感兴趣的:(嵌入式linux开发,嵌入式linux开发,gdb调试内核,gdb扩展命令)