感谢@Richar,教我配出了超级方便的LLVM Pass源码级调试环境 Orzzzz
准备工作
- 按照前一篇博客 LLVM编译与FirstPass 配置好LLVM环境和环境变量,LLVM必须用Debug模式编译
- 安装好vscode 如果用的是虚拟机则配好vscode remote ssh,WSL的话配好vscode remote WSL
Vscode
本来我是想直接将调试环境配置到LLVM源码根目录。但是尝试之后发现用Remote的方式打开源码根目录,vscode要加载的东西太多,代码联想等功能都非常慢,体验很差。因为我们要调试的基本是自己写的Pass,后面发现可以直接配到自己Pass的目录下(这个目录可以在任意位置),然后把包含目录配置到vscode配置文件中就可以了。
现在,假定自己要开发的Pass目录名为MyPass,其中有Pass源代码文件 MyPass.cpp,目标源文件 target.cpp。在MyPass目录下,创建一个.vscode文件夹,在.vscode文件夹中建立三个文件
|
|
|
|
|
|
以上是.vscode目录下所有配置的内容。然后回到MyPass目录,需要再配置一个makefile
|
|
大概就是配置这些文件。然后要使用的话,切记要用Remote模式的vscode。比如是WSL的,则要在WSL Shell中敲 “code .”来启动vscode,虚拟机的话则用vscode Remote SSH并打开对应文件夹。然后就可以按快捷键愉快build和调试自己的Pass了
- F5调试
- Ctrl+Shift+B Run
- 终端->运行任务 里面可以看到并运行配置的所有任务
Visual Studio
同样也是先按照LLVM 编译与First Pass配置好LLVM环境,根据cmake生成sln工程后在工程里编译一份。同样的也是建议用Debug模式编译,LLVM自身的编译优化等级很高,在Release或者RelWithDebInfo模式下编译挂源码调试,会出现很多局部变量被优化看不到值,纯靠猜。但是Debug模式编译已经很慢了,再加上VisualStudio的调试模式,慢+卡,非常的折磨
如果是单cpp文件的编译调试非常简单,不讲了,这边要介绍的是当有一个A.sln工程要用clang编译的时候,我们怎么完美复现环境并用vs调试clang
用VisualStudio来调试比vscode要方便很多,因为环境不用自己配了。我们可以先用LLVM报错排查技巧 -### 方法拿到A.sln工程底层传递到clang编译时的命令,比如
Build started...
1>------ Build started: Project: test, Configuration: Release x64 ------
1>clang version 19.0.0git QVMProtect Release
1>Target: x86_64-pc-windows-msvc
1>Thread model: posix
1>InstalledDir: D:\LLVM\WindowsRelWithDebInfo\bin
1> (in-process)
1> "D:\\LLVM\\WindowsRelWithDebInfo\\bin\\clang-cl.exe" "-cc1" "-triple" "x86_64-pc-windows-msvc19.29.30151" "-emit-obj" "-mrelax-all" "-mincremental-linker-compatible" "-disable-free" "-clear-ast-before-backend" "-disable-llvm-verifier" "-discard-value-names" "-main-file-name" "test.cpp" "-mrelocation-model" "pic" "-pic-level" "2" "-mframe-pointer=none" "-relaxed-aliasing" "-fmath-errno" "-ffp-contract=on" "-fno-rounding-math" "-mconstructor-aliases" "-fms-volatile" "-funwind-tables=2" "-target-cpu" "x86-64" "-target-feature" "+avx" "-target-feature" "+avx2" "-mllvm" "-x86-asm-syntax=intel" "-tune-cpu" "generic" "-D_MT" "-flto-visibility-public-std" "--dependent-lib=libcmt" "--dependent-lib=oldnames" "-stack-protector" "2" "-fcxx-exceptions" "-fexceptions" "-fexternc-nounwind" "-fdefault-calling-conv=cdecl" "-fdiagnostics-format" "msvc" "-gno-column-info" "-gcodeview" "-debug-info-kind=constructor" "-fdebug-compilation-dir=E:\\code\\test" "-object-file-name=E:\\code\\test\\x64\\Release\\test.obj" "-ffunction-sections" "-fcoverage-compilation-dir=E:\\code\\test" "-resource-dir" "D:\\LLVM\\WindowsRelWithDebInfo\\lib\\clang\\19" "-D" "NDEBUG" "-D" "_CONSOLE" "-D" "_UNICODE" "-D" "UNICODE" "-internal-isystem" "D:\\LLVM\\WindowsRelWithDebInfo\\lib\\clang\\19\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.29.30133\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.29.30133\\atlmfc\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Auxiliary\\VS\\include" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\um" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\shared" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\winrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\cppwinrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.29.30133\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Tools\\MSVC\\14.29.30133\\atlmfc\\include" "-internal-isystem" "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Professional\\VC\\Auxiliary\\VS\\include" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\ucrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\um" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\shared" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\winrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\10\\Include\\10.0.19041.0\\cppwinrt" "-internal-isystem" "C:\\Program Files (x86)\\Windows Kits\\NETFXSDK\\4.8\\Include\\um" "-O0" "-Wall" "-Wno-error" "-Wsystem-headers" "-fdeprecated-macro" "-ferror-limit" "19" "-fno-use-cxa-atexit" "-fms-extensions" "-fms-compatibility" "-fms-compatibility-version=19.29.30151" "-std=c++20" "-fno-implicit-modules" "-fskip-odr-check-in-gmf" "-fno-caret-diagnostics" "-faddrsig" "-o" "x64\\Release\\test.obj" "-x" "c++" "test.cpp"
然后在LLVM的工程中,找到clang项目,配置clang项目的属性,clang Project -> Properties -> Configuration Properties -> Debugging
- Command:$(TargetPath),也就是clang.exe
- Command Arguments:把clang-cl.exe后面的参数直接全部复制进去
- Working Directory: 这里填A.sln工程的路径
完事后,打上断点,在clang工程上右键,Debug -> Start New Instance启动调试。当然,用这种方法的调试,是不可以调试外部Pass模块的,比如你将pass编译成了一个.dll然后用接口或者任意的LoadLibrary等方式拉起加载,然后对着外部模块的源码断点是无法命中的,即使外部模块的项目挂在LLVM工程下也是不行的