在Mac OS X上获取当前的堆栈跟踪 [英] Getting the current stack trace on Mac OS X

查看:352
本文介绍了在Mac OS X上获取当前的堆栈跟踪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图弄清楚如何在Mac OS X上的C ++应用程序中存储然后打印当前堆栈.主要问题似乎是当在主可执行文件中给定地址时,dladdr返回正确的符号.我怀疑这个问题实际上是一个编译选项,但是我不确定.

I'm trying to work out how to store and then print the current stack in my C++ apps on Mac OS X. The main problem seems to be getting dladdr to return the right symbol when given an address inside the main executable. I suspect that the issue is actually a compile option, but I'm not sure.

我尝试了Darwin/Leopard的回溯代码,但它调用了dladdr,并且与我自己的调用dladdr的代码具有相同的问题.

I have tried the backtrace code from Darwin/Leopard but it calls dladdr and has the same issue as my own code calling dladdr.

原始帖子: 目前,我正在使用以下代码捕获堆栈:

Original post: Currently I'm capturing the stack with this code:

int BackTrace(Addr *buffer, int max_frames)
{
    void **frame = (void **)__builtin_frame_address(0);
    void **bp = ( void **)(*frame);
    void *ip = frame[1];
    int i;

    for ( i = 0; bp && ip && i < max_frames; i++ )
    {
        *(buffer++) = ip;
        ip = bp[1];
        bp = (void**)(bp[0]);
    }

    return i;
}

似乎工作正常.然后使用以下命令使用dladdr打印堆栈:

Which seems to work ok. Then to print the stack I'm looking at using dladdr like this:

Dl_info dli;
if (dladdr(Ip, &dli))
{
    ptrdiff_t       offset;
    int c = 0;

    if (dli.dli_fname && dli.dli_fbase)
    {
        offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_fbase;
        c = snprintf(buf, buflen, "%s+0x%x", dli.dli_fname, offset );
    }
    if (dli.dli_sname && dli.dli_saddr)
    {
        offset = (ptrdiff_t)Ip - (ptrdiff_t)dli.dli_saddr;
        c += snprintf(buf+c, buflen-c, "(%s+0x%x)", dli.dli_sname, offset );
    }

    if (c > 0)
        snprintf(buf+c, buflen-c, " [%p]", Ip);

几乎可以正常工作的示例输出:

Which almost works, some example output:

/Users/matthew/Library/Frameworks/Lgi.framework/Versions/A/Lgi+0x2473d(LgiStackTrace+0x5d) [0x102c73d]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2a006(tart+0x28e72) [0x2b006]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x2f438(tart+0x2e2a4) [0x30438]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x35e9c(tart+0x34d08) [0x36e9c]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x1296(tart+0x102) [0x2296]
/Users/matthew/Code/Lgi/LgiRes/build/Debug/LgiRes.app/Contents/MacOS/LgiRes+0x11bd(tart+0x29) [0x21bd]

它正在为共享对象而不是主应用程序获取正确的方法名称.那些只是映射到"tart"(或"start"减去第一个字符).

It's getting the method name right for the shared object but not for the main app. Those just map to "tart" (or "start" minus the first character).

理想情况下,我想要行号以及方法名.但是我将为初学者确定正确的函数/方法名称.也许在那之后拍摄行号,在Linux上,我听说您必须为具有自己指令集的私有ELF块编写自己的解析器.听起来很吓人.

Ideally I'd like line numbers as well as the method name at that point. But I'll settle for the correct function/method name for starters. Maybe shoot for line numbers after that, on Linux I hear you have to write your own parser for a private ELF block that has it's own instruction set. Sounds scary.

无论如何,任何人都可以整理出这段代码,以便正确获取方法名称吗?

Anyway, can anyone sort this code out so it gets the method names right?

推荐答案

您要定位哪些OS X版本.如果您在Mac OS X 10.5和更高版本上运行,则可以仅使用backtrace()和backtrace_symbols()libraray调用.它们在execinfo.h中定义,并且有一个

What releases of OS X are you targetting. If you are running on Mac OS X 10.5 and higher you can just use the backtrace() and backtrace_symbols() libraray calls. They are defined in execinfo.h, and there is a manpage with some sample code.

您在评论中提到需要在Tiger上运行.您可能只需要在应用程序中包含Libc的实现即可.该资源可从Apple的开放源代码网站上获得.这是到relevent 文件的链接.

You mentioned in the comments that you need to run on Tiger. You can probably just include the implementation from Libc in your app. The source is available from Apple's opensource site. Here is a link to the relevent file.

这篇关于在Mac OS X上获取当前的堆栈跟踪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆