最近在做Windows下的客户端代码在Mac下编译运行,其中界面是基于Qt开发的,跨平台编译倒是很快搞定了,但是在定位问题时却遇到了写问题。在xcode IDE中基本的打断点、查看堆栈都是有的,但对于一些疑难的问题想跟Qt的源码却费了些功夫。在VS环境下,只要把三方库的源码拖到编辑器中,随便怎么打断点都是能做调试的,同样的方法在Xcode下行不通。
其本质原因是在符号文件中记录的源码路径与当前实际的源码路径不一致,调试器按记录的路径去找源码肯定是找不到的。尤其对项目中使用的三方库,鬼知道它在编译是源码是放在哪的。所以对于自己编译的成果物无论是附加调试还是直接运行调试都是能够做本地调试的,因为源码路径是匹配的。
那么问题来了,如何引导调试器找到正确的文件路径?在Xcode中调试相关的只有一个Debug Area,没有看到配置源码加载的入口。但是,有一个调试器的命令窗口。这个窗口在运行中不那么显眼,但在命中断点或手动暂停程序执行的时候就能看到。如下图所示位置:
看到这个窗口我想到了Windows下的WinDBG,理论上WinDBG下有的类似打断点、查看符号及加载模块等在这里都是有对应命令的。因此,可以获取界面上展示的断点、堆栈外的更多的是状态信息。
help命令可以获取lldb支持的所有命令,对于每个主命令,还有相关的子命令。如Image命令可以获取当前进程加载的模块信息,其支持的子命令包括加载模块、查看当前已加载的模块及符号查找等。对于调试而言,我们最关心的就是符号文件有没有加载,image list查看:
可以看到Qt的库是加载了匹配的符号文件的。若符号没有加载,则可能是符号文件匹配或者符号文件加载路径没有配置。Mac下符号文件的匹配是通过GUID,库文件和dYSM文件都有唯一 的GUID,可通过校验GUID确定是否匹配;符号路径则可以通过lldb的add-dsym工具添加符号所在路径。在符号文件加载之后,我们就可以查找指定的符号打断点了。如:
在命中断点后,source命令查看源码路径:
这个源码路径在我们本地显然是不存在的,lldb支持源码的文件路径映射。如果在Qt安装时选择了安装源码, 那么可通过下述命令修改源码路径映射:
这样就能够在命中断点时加载匹配的源文件并可继续调试。当然,是否能做源码调试依赖于符合文件记录的调试信息是否完整,比如Qt的Rlease版本也带符号文件的,调试时也能命中毒啊断点,但因为开了优化等原因导致符号文件中并无源码信息,所以即便配置源码路径也是无法加载的。所以上述示例中用的都是debug版本的Qt库。
在本篇中只是展示了lldb的部分命令感兴趣的话可以研究下其他命令,如线程堆栈切换等,掌握这些调试命令能够加快问题排查的进度。此外,上述方式也用于挂载调试的场景,此时成果物可能来自编译服务器,而非你本地,那么也是要通过源码映射方式修改加载路径的,否则即便源码为同一版本attach之后依然无法调试。