最近笔者在MinGW下使用GCC+NASM组合时,遇到一个问题,就是在使用GDB调试时,NASM汇编代码没有调试信息。

MinGW下,GCC/Clang编译器编译时,都是使用的dwarf调试格式的调试信息;而MSVC使用的是Codeview格式的调试信息。

NASM在Windows下默认生成的都是PE格式,其调试信息也只能是Codeview格式。所以如果是MSVC+NASM的组合,NASM的代码是可以正常使用调试信息的。而MinGW下的GCC/Clang生成的dwarf格式无法与NASM的Codeview格式混合,所以MinGW下的GCC/Clang就会把NASM生成的obj文件中的调试信息忽略掉,导致不管是VS2022的调试器还是GDB/LLDB调试器都无法使用NASM代码的调试信息。

笔者经过尝试,发现在MinGWNASM可以生成ELF格式的obj文件,GCC也可以正常链接,而且添加-g参数后,默认生成dwarf格式的调试信息,链接生成的EXE文件中存在相应的调试信息,GDB调试器可以正常使用NASM生成的调试信息。

在CMakeLists.txt中如下写:

1set(CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS asm) # 指定NASM编译的源码扩展名为asm
2set(CMAKE_ASM_NASM_FLAGS "-g") # 添加调试信息
3if(MINGW) # MINGW下强制使用elf64格式
4set(CMAKE_ASM_NASM_OBJECT_FORMAT elf64) # 设置生成的obj文件格式为elf64,Windows下默认为win32/win64,Linux默认为elf32/elf64
5endif()
6ENABLE_LANGUAGE(ASM_NASM) # 启用NASM汇编

如果是Makefile或者命令行,直接添加下面的参数即可:

1-g -f elf64

GDB调试效果如下图所示,可以在源码中直接打断点:

在这里插入图片描述

MSVC+NASM,使用MS调试器的效果如下所示,可以反汇编的同时看源码:

在这里插入图片描述

目前最新的VS2022 17.14.13,CMake项目中使用MinGW编译套件生成的EXE文件,是可以直接使用VS2022调试的,而不需要配置GDB。也就是说VS2022已经具备了直接调试dwarf格式的EXE文件,虽然是使用的Remote Debugger,即远程调试。但是可能支持还不太完善,这种方式还不能调试GCC+NASM生成的EXE中NASM汇编源码。GDB能调试还是非常不错的!

如果本文对你有帮助,欢迎点赞收藏!