如何解决VS Code中用LLDB调试Delphi Win32程序的调用栈异常问题?
解决VS Code中Delphi调试LLDB调用栈异常及符号问题
一、搞定LLDB调用栈指向__dbk_fcall_wrapper的问题
__dbk_fcall_wrapper是Delphi自带的调试包装函数,LLDB没正确解析符号映射才会一直显示它,试试下面几个方案:
调整map2pdb的生成参数
有些版本的map2pdb会保留调试包装函数的符号,强制剥离就能解决。如果用YAML中转的方式,加-no-wrap参数:map2pdb -bind -no-wrap Tester.map要是直接生成PDB,试试
-strip-wrapper参数(需确认你的map2pdb版本支持):map2pdb -strip-wrapper Tester.exe Tester.map手动修正PDB符号表
先用llvm-pdbutil导出PDB的符号:llvm-pdbutil dump -symbols Tester.pdb > symbols.yaml打开yaml文件,找到所有带
__dbk_fcall_wrapper的条目,把它们的RelativeVirtualAddress替换成对应真实方法的RVA(从你的MAP文件里找,比如MyUnit.TMyClass.MyMethod的RVA是00010042)。改完后重新生成PDB:llvm-pdbutil yaml2pdb -o Tester_fixed.pdb symbols.yaml给LLDB加启动规则
在VS Code的launch.json里配置LLDB的启动命令,强制跳过包装函数的符号匹配:{ "type": "lldb", "request": "launch", "name": "Delphi Debug", "program": "${workspaceFolder}/Tester.exe", "args": [], "cwd": "${workspaceFolder}", "lldb": { "launchCommands": [ "settings set target.process.skip-prologue false", "symbol lookup -r \"^__dbk_fcall_wrapper$\" -e Tester.exe", "symbol replace __dbk_fcall_wrapper 0x00410042" // 替换成真实方法的内存地址 ] } }真实方法的内存地址可以用LLDB命令
image lookup -n MyUnit.TMyClass.MyMethod获取。
二、解决GDB的“无调试符号”问题
- 先确保Delphi编译时生成了详细MAP文件:打开项目选项→Linker→Map file,选Detailed。
- 换用
cv2pdb工具生成PDB,它对Delphi符号的兼容性比map2pdb好:cv2pdb Tester.exe Tester.map - 在VS Code的
launch.json里给GDB指定符号文件路径:{ "type": "cppdbg", "request": "launch", "name": "GDB Debug Delphi", "program": "${workspaceFolder}/Tester.exe", "stopAtEntry": false, "cwd": "${workspaceFolder}", "MIMode": "gdb", "miDebuggerPath": "gdb.exe", "symbolSearchPath": "${workspaceFolder}", "setupCommands": [ {"text": "symbol-file Tester.pdb"} ] }
三、优化WinDbg在VS Code中的支持
- 换成WinDbg Preview,它的VS Code插件支持度比旧版高很多。
- 配置
launch.json用WinDbg调试:{ "type": "windbg", "request": "launch", "name": "WinDbg Debug Delphi", "program": "${workspaceFolder}/Tester.exe", "cwd": "${workspaceFolder}", "symbolPath": "${workspaceFolder}", "sourcePath": "${workspaceFolder}/Source" // 改成你的Delphi源码目录 } - 源码匹配问题:先用WinDbg命令
!lmi Tester.exe查看编译时记录的源码路径,如果和现在的工作目录不一致,用.srcfix手动映射:.srcfix C:\Old\Source\Path C:\Current\Workspace\Source
四、额外小技巧
- 在Delphi代码里插
asm int 3; end;手动触发断点,这时LLDB/GDB中断后查看调用栈,大概率能绕过包装函数。 - 用Delphi的
DebugHook单元输出调用栈到控制台,和调试器的输出对比,确认符号映射是否正确。
内容的提问来源于stack exchange,提问作者Laurens
相关产品推荐
相关产品推荐

