一次难忘的调试

一次难忘的调试


今天在 buildroot 上交叉编译 gstreamer 的时候,发现一个诡异的问题。
版本:
buildroot 2011.11-rc3
gstreamer-0.10.35
arm-none-linux-gnueabi-gcc-4.5.2

编译出来之后调用 gst-inspect shmsrc,发现信息没有打印完就出现 Abort 错误。
而 gst-inspect mpegtsmux 或者 v4l2src 还有其他的组件也有类似的错误。
如下所示:


这可能是收到了一个 Abort 信号导致退出的,而不是程序正常结束。
于是在 buildroot 上选中 gdb 并且选择带调试信息编译(-g3)。
用 gdb 调试的时候,定位到出错位置,堆栈打印如下:



可见它是在 print_element_info 内发生的错误,而上面打印的信息也是在 “Element Implementation:” 这一句话后终止的。
接下来的 g_strdup_printf 以及一系列的 g 打头的函数都是 glib 里面的代码。
奇怪了,这类常用的函数怎么可能会出错呢?
历经周折,最后发现最底层调用的是 sprintf 函数。


而在 sprintf 的断点处,确发现函数的参数都是正常的。
真是十分诡异的现象。


而 lib 的 sprintf 已经没有源码了,于是用 si 逐指令跟踪。按了半分多种忽然有重大发现!
一开始一直在 vfprintf 里面,然后跳转到一个底层的 __parse_one_specmb 函数。
居然瞬间又跳转到一个 gstreamer 中的函数 _gst_info_printf_extension_arginfo!


这个函数究竟是何方神圣,看起来像是一个 printf 扩展类的回调函数。
发现了真身,这到底是什么东西?
一次难忘的调试_第1张图片

搜了一下,找到了 GNU 的官网,发现是 printf 的扩展功能。是 glibc 2.0 版本以后的新东西。
http://www.gnu.org/software/libc/manual/html_node/Registering-New-Conversions.html#Registering-New-Conversions

一次难忘的调试_第2张图片
发现它是可有可无的。
在 configure 里注释掉它,在 buildroot 的 package 里加了一个 patch,然后重新 make。



一切正常了!哈哈!

一次难忘的调试_第3张图片

最后发现早在2011年1月份就有老外发现了这个问题。 https://bugzilla.gnome.org/show_bug.cgi?id=638599
貌似是跟 glib 的一些机制相关。
可能是影响范围不够广,还没有导致到要取消掉这个机制。



虽然说为了一个莫名其妙的问题忙活了半天,但学了一些 gdb 命令,而且还知道了 printf 原来还能扩展。很神奇的东西。

你可能感兴趣的:(一次难忘的调试)