« 换了个新手机 | 返回首页 | Windows 下调试问题一则 »

mingw 下的 stack backtrace

我们的项目的 Windows 版本是用 MinGW 开发的。当程序在 Windows 下挂掉后,固然可以用 gdb 调试,看到调用栈。但有些时候还是不够方便。

比如说今天,我们写的模型编辑器发到广州美术同事使用时,就出了问题。3d 程序在不同显卡环境下的确容易出故障,异地调试程序非常困难。这个时候,多么想看看调用栈啊。

The GNU C Library 是提供了 Backtraces 的,可惜 MinGW 不支持 :( 。最后打算自己写一个。

获取 stack backtrace 调试信息的基本原理就是利用 windows 的 imagehlp.dll 取得正在运行的 exe 或 dll 被系统加载到内存后的镜像信息(可能被重定位了)。然后利用 libbfd 按偏移量取得源码的相关信息。

在崩溃时获取调用栈信息使用的是 SetUnhandledExceptionFilter ,可以注册一个函数拿到 context 继续处理。

搜索一番后,发现其实有个哥们实现了个 C++ 版本 。不过我还是用我自己写的 C 版本吧。

使用非常简单,只需要把事先编译好的 backtrace.dll 在需要追踪的程序前面加载一下即可,然后在 crash 时就会向 strerr 输出详细的堆栈信息。

有兴趣的同学可以看这里:我把它在 code.google.com 上开源了

Comments

不需要-lintl也能编译backtrace64.dll成功,那-lintl有什么作用?对这个的确不了解.
另外,exception_filter中的函数调用非常严格,在这里调用SymInitialize失败概率较高.应该改成主程序负责SymInitialize和SymCleanup

新代码在这里https://github.com/cloudwu/backtrace-mingw
但是编译还没有成功

你好,我用i686-5.3.0-release-win32-dwarf-rt_v4-rev0这个版本的mingw编译的时候,出错,提示backtrace.c:23:17: fatal error: bfd.h: No such file or directory

请问应该怎么解决呀?或者现在有什么新的解决方案吗?

哈哈,终于看到回复了。
另外有个小建议就是set的空间分配,开始不用在调用_backtrace之前分配一个节点,全部放到get_bc好了。个人感觉有点怪

@wosinwu

已经修正了 :)

release_set似乎有bug
应该是while(set)吧,不然最后一个节点删不掉

前几天的版本有点问题,只能显示 exe 里的栈,如果有额外加载的 dll 就搞不定了。

今天修正了这个问题。

bfd *b = bfd_openr(procname, 0);
这行总是返回NULL,打印下procname的值,是没问题的。

gcc -O2 -shared -Wall -o backtrace.dll backtrace.c -lbfd -liberty -limagehlp -lintl 编译成功,但测试时仍然出现错误,“Failed to init bfd”

我更新了 Mingw 版本后发现也缺少 intl 库,现在更新了,在 Makefile 里加上 -lintl 就可以了。

缺少 libintl 的可以去
http://gnuwin32.sourceforge.net/packages/libintl.htm

下载安装 libintl 0.14

支持!!!

支持你

哈哈,是也

@missdeer

加一个 -lintl 看看。
我的版本的 MinGW 是没有这个库的。

链接不成功:
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(libbfd.o):libbfd.c:(.tex
t+0x6ee): undefined reference to `libintl_dgettext'
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(libbfd.o):libbfd.c:(.tex
t+0x740): undefined reference to `libintl_dgettext'
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(libbfd.o):libbfd.c:(.tex
t+0x79b): undefined reference to `libintl_dgettext'
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(libbfd.o):libbfd.c:(.tex
t+0x7d0): undefined reference to `libintl_dgettext'
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(bfd.o):bfd.c:(.text+0x8f
d): undefined reference to `libintl_dgettext'
g:/mingw/bin/../lib/gcc/mingw32/4.4.0/../../../libbfd.a(bfd.o):bfd.c:(.text+0x96
4): more undefined references to `libintl_dgettext' follow

http://code.google.com/p/google-breakpad/wiki/GettingStartedWithBreakpad

Google做的开源项目breakpad,可以获得stack traces信息...

Only the Microsoft tools use the proprietary PDB format. The GNU tools use STABS or DWARF-2 for the debug information.

@fseraph

pdb 是 MS 的私有格式,生成 pdb 文件的工具并没有开源。mingw (以及现有的 GNU 工具?) 无法生成 pdb 文件。

如果在windows下收集dump,其实也可以考虑用Windbg提供的脚本为Build脚本加入一个Symbol Store的过程,搭建一个Symbol Server,只要正确的索引PDB文件,用Windbg或者VS打开崩溃之后的dump文件就可以自动获取编译这个版本时的源代码信息,蛮方便的。而且任意版本都可以看。

好神奇。。。

backtrace这种神器一定要顶!

内牛满面

Post a comment

非这个主题相关的留言请到:留言本