在Mac OS X上获取当前堆栈跟踪

时间:2023-01-21 14:29:17

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.

我正在努力研究如何在Mac OS x上的c++应用程序中存储并打印当前堆栈。我怀疑这个问题实际上是一个编译选项,但我不确定。

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

我尝试了来自Darwin/Leopard的回溯代码,但它调用了dladdr,与我自己调用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;
}

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

看起来还行。然后打印堆栈,我正在使用dladdr如下:

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]

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).

它是为共享对象获取方法名,而不是主应用程序。那些只是映射到“tart”(或“开始”减去第一个字符)。

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.

理想情况下,我希望得到行号和方法名。但是对于初学者,我还是选择正确的函数/方法名。在那之后,我听说在Linux上,你必须为私有的ELF块编写自己的解析器,它有自己的指令集。

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

不管怎样,谁能把这些代码排序出来,这样它就能得到正确的方法名?

1 个解决方案

#1


12  

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.

你打算发布什么OS X。如果您正在Mac OS X 10.5或更高版本上运行,您可以使用backtrace()和backtrace_symbols() libraray调用。它们是在execinfo中定义的。h,这里有一个包含一些示例代码的manpage。

Edit:

编辑:

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.

您在评论中提到您需要运行Tiger。你可以在你的应用程序中包含来自Libc的实现。这是一个到相关文件的链接。

#1


12  

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.

你打算发布什么OS X。如果您正在Mac OS X 10.5或更高版本上运行,您可以使用backtrace()和backtrace_symbols() libraray调用。它们是在execinfo中定义的。h,这里有一个包含一些示例代码的manpage。

Edit:

编辑:

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.

您在评论中提到您需要运行Tiger。你可以在你的应用程序中包含来自Libc的实现。这是一个到相关文件的链接。