Xcode 单步调试 WebRTC

前言

最近使用 WebRTC 开发一个实时直播项目,在调试的时候发现一个特别奇怪的现象,将编译好的 WebRTC 静态库文件加入到我们自己的工程里之后无法进行单步调试。每次调到 WebRtc 里都会变成汇编语言,如果如下:

看到这个现象后,我分析有以下几种这种情况可能导致这类问题:

  • Xcode中勾选了Always Show Disassembly
  • 生成的静态库中没有符号表。
  • 有符号表,但没有与源文件关联到一起。

下面我们来详细说一下这几种情况。

勾选了 Show Disassembl

如果是这个原因导致的那是最好解决的了。我们只需查看Xcode里下面这项是否勾选了,即可确定是不是它导致的问题了。

Xcode->Debug->Debug Workflow->Always Show Disassembly

如果该项处于勾选状态,只需去掉勾选就可以解决上面的问题了。

生成的静态库没有符号表

如何判断是否是由于没有符号表导致无法单步调试的呢?我们在 Linux 下经常用下面这个命令:

  • nm : 显示二进制目标文件的符号表。

一般的用法是 nm 可执行文件/库文件 | grep 函数名

该命令不光可以在 Linux 上使用,在 Mac 上同样可以使用。如果通过上面的方法查不到相找的函数名,那么说明程序里就没有符号表。

如何解决没有符号表的问题呢?学过编译原理的同学们都知道,程序在编译的时候必须要有符号表的。因为在生成可执行程序之前的链接阶段,需要通过符号表进行最终的地址定位与程序链接。

也就是说,如果没有看到符号表,那说明是被人为的拿掉了。我们一般会使用strip命令去掉符号表,以减少目标程序的大小。命令如下:

strip a.out

为了确认是否是被人为的拿掉了,可以通过命令行查看 Xcode 执行编译时是否调用了strip命令。通过执行下面的命令就可以看到 Xcode 的编译命令了。

xcodebuild -scheme 工程名

一般情况下,在Xcode中除非是生成 Release 程序,否则的话基本是不会调用 strip 命令的。所以如果出现上述情况,就要详细查看一下 Xcode 的工程配置了。

有符号表,但没有与源文件关联到一起

大家看到符号表与源代码关联是不是觉得很奇怪?大部分人只听过符号表,从来没有听过符号表与源代码关联这类说法。

没错,调试器就是使用符号表与源代码关联文件来达到调试效果的。我举个简单的例子大家就清楚了,无论你在什么平台上使用什么语言,如 OC, linux下的 c/c++, java等,你一定用过单步调式或断点调试。

在调试时,debugger会高亮显示你所执行的代码行,并且你可以看到对应该行的各种变量的值。那么debugger是如何做到的呢?它就是通过一张映射表做到的这种效果。每一个符号都对应一个文件及所在行数,当执行到该行时,就将对应的代码显示出来,这就是 debugger的工作原理。

如果我们进行单步调试时不能显示代码行,那很有可能是这个原因导致的。

我们如何验证是否是由于这个原因导致的问题呢?在xcode里提供了一个非常有用的工具dwarfdump,它非常强大,与 Linux 系统下的 readelf 工具差不多,可以打印出可执行程序的详细信息。

我们可以执行下面的命令,查看是否有相关的信息即可确认是否是由于这个原因导致的问题了。

dwarfdump 可执行文件/库文件

执行结果如下所示:


工程问题

如果以上办法都无法解决的话,那么基本可以确定是你所建的工程有问题了。目前这类问题还没有找到更好的解决办法,所以对于这类问题处理的方式也很简单,重建一个新的工程就好了。

小结

上面是我在工作中遇到的一个问题。无法对项目进行单步调试,严重的影响到了我们解决问题的进度。为了解决该问题,我几乎将 Xcode 的编译与调试机制翻了个遍。

从另一个方面廛,想要尽快的熟悉一个项目的代码,熟练使用单步调试方法是一个捷径。对于 WebRTC 项目更是如此。WebRTC是一个非常庞大的项目,如果没有好的方法,光靠我们自己阅读代码很容易掉入坑中而不能自拔。

至此,我已经将 Xcode 单步调试机制讲清楚了,希望本文能对你所有帮助,谢谢!

推荐阅读更多精彩内容