用-O0编译Linux 5.15内核调试遇报错,求解决及替代方法
内核调试问题:-O0编译失败及替代调试方案
问题背景
调试Linux内核v5.15时,通过make menuconfig开启DWARF调试信息后,gdb逐行调试仍存在代码行被跳过的情况。发现默认编译优化级别为-O2,于是修改Makefile尝试全局改为-O0:
ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE KBUILD_CFLAGS += -O2 # here change to -O0 else ifdef CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE_O3 KBUILD_CFLAGS += -O3 else ifdef CONFIG_CC_OPTIMIZE_FOR_SIZE KBUILD_CFLAGS += -Os endif
执行编译命令:
make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- -j$(nproc)
出现如下编译错误:
CALL scripts/checksyscalls.sh CALL scripts/atomic/check-atomics.sh CC init/main.o In file included from ././include/linux/compiler_types.h:85, from <command-line>: ./arch/riscv/include/asm/jump_label.h: In function ‘want_init_on_alloc’: ./include/linux/compiler-gcc.h:88:38: warning: ‘asm’ operand 0 probably does not match constraints 88 | #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) | ^~~ ./arch/riscv/include/asm/jump_label.h:20:9: note: in expansion of macro ‘asm_volatile_goto’ 20 | asm_volatile_goto( | ^~~~~~~~~~~~~~~~~ ./include/linux/compiler-gcc.h:88:38: error: impossible constraint in ‘asm’ 88 | #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) | ^~~ ./arch/riscv/include/asm/jump_label.h:20:9: note: in expansion of macro ‘asm_volatile_goto’ 20 | asm_volatile_goto( | ^~~~~~~~~~~~~~~~~ ./arch/riscv/include/asm/jump_label.h: In function ‘want_init_on_free’: ./include/linux/compiler-gcc.h:88:38: warning: ‘asm’ operand 0 probably does not match constraints 88 | #define asm_volatile_goto(x...) do { asm goto(x); asm (""); } while (0) | ^~~ ./arch/riscv/include/asm/jump_label.h:20:9: note: in expansion of macro ‘asm_volatile_goto’ 20 | asm_volatile_goto( | ^~~~~~~~~~~~~~~~~ make[1]: *** [scripts/Makefile.build:277: init/main.o] Error 1 make: *** [Makefile:1868: init] Error 2
若无法修改全局编译优化参数,可采用以下更细粒度的调试方案:
替代调试方案
1. 仅针对目标代码关闭优化
不要全局修改-O2为-O0,而是对需要调试的特定文件或目录单独设置编译选项:
- 单个文件:在目标文件所在目录的Makefile中添加
CFLAGS_main.o := -O0 -g - 整个目录:在该目录的Makefile中加入
KBUILD_CFLAGS := $(KBUILD_CFLAGS:-O2=-O0)
这种方式仅让关注的代码段无优化编译,避免全局修改触发的汇编约束错误。
2. 利用gdb高级调试功能
即使是-O2编译的内核,也可通过gdb命令缓解代码跳转问题:
set step-mode on:开启后逐指令执行,不会跳过因优化合并的代码行info line <function>:查看函数对应的汇编行,手动设置断点到汇编指令break *&function_name:直接在函数起始地址设置断点,避免符号优化导致的断点失效disassemble:查看当前代码的汇编,结合源码逐指令调试
3. 内核自带调试工具辅助
- printk:在关键代码位置添加
printk(KERN_DEBUG "xxx: val=%d\n", val);,通过dmesg查看输出跟踪执行流程 - ftrace:开启内核ftrace相关配置后,可跟踪函数调用、执行时间,无需修改代码或重新编译
- kprobes:动态插入探针,运行时获取函数参数、返回值,适合无法重新编译的场景
4. 调整内核编译选项
在make menuconfig中开启以下选项提升调试体验:
CONFIG_DEBUG_INFO_DWARF4=y:使用更完善的DWARF4格式,提升gdb解析能力CONFIG_FRAME_POINTER=y:开启帧指针,帮助gdb更好地回溯调用栈CONFIG_OPTIMIZE_INLINING=n:关闭函数内联,减少代码行被跳过的情况
内容的提问来源于stack exchange,提问作者Lemonorn
相关产品推荐
相关产品推荐

