为什么回溯不包含Objective-C符号而不管-rdynamic? [英] Why does backtrace not contain Objective-C symbols regardless of -rdynamic?

查看:178
本文介绍了为什么回溯不包含Objective-C符号而不管-rdynamic?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:我正在使用Linux上的GNU运行时。



更新2:我编译了GNU-在MacOS上运行,并用它构建示例。 GNU运行时在MacOS上发生错误 not 。我会说问题是glibc(因为 backtrace backtrace_symbols 是glibc扩展名)。



使用 backtrace backtrace_symbols ,我没有得到任何Objective-C符号。只有文件名,地址和C符号才会出现。



我使用 -g 编译并链接到<$ c


$ p <我的测试应用程序:

  void _printTrace()
{
void * addr [1024];
int aCount = backtrace(addr,1024);
char ** frameStrings = backtrace_symbols(addr,aCount);
for(int i = 0; i< aCount; i ++){
printf(%s \ n,frameStrings [i]);
}
free(frameStrings);
}

@interface TheObject
+(void)_printTrace;
+(void)printTrace;
@end

@implementation TheObject
+(void)_printTrace
{
_printTrace();
}

+(void)printTrace
{
[self _printTrace];
}
@end

void printTrace()
{
[TheObject printTrace];


int main(int argc,char ** argv)
{
printTrace();
返回0;
}

以及它的输出:

  ./ test.bin(_printTrace + 0x1f)[0x8048e05] 
./test.bin()[0x8048e60]
./test.bin() [0x8048e8b]
./test.bin(printTrace+0x34)[0x8048ec5]
./test.bin(main+0xf)[0x8048eda]
/lib/libc.so.6( __libc_start_main + 0xe5)[0xb7643bb5]
./test.bin()[0x8048b51]

有没有一种方法让Objective-C符号出现在这个回溯中?

解决方案

dladdr() 仅报告全局和弱符号。但是所有的Objective-C函数符号都是本地的:

  $ readelf -s so_backtrace 

符号表' .dynsym'包含29个条目:
...

符号表'.symtab'包含121个条目:
编号:值大小类型绑定Vis Ndx名称
...
49:08048a01 13 FUNC LOCAL DEFAULT 14 _c_TheObject___printTrace
50:08048a0e 47 FUNC LOCAL DEFAULT 14 _c_TheObject__printTrace
...

您可以通过查看 GNU libc源代码 backtrace_symbols()在sysdeps / generic / elf / backtracesyms.c中定义。它依赖于elf / dl-addr.c中定义的 _dl_addr()来为它提供符号名称。这最终会调用 determine_info()。如果可以的话,它使用 GNU哈希表,它不包含本地符号设计:

  49 / *我们查看哈希
50表引用的所有符号表条目。 * /
...
60 / *散列表从不引用本地符号,所以
61我们可以在这里省略这个测试。 * /

如果GNU哈希表不存在,它将回退到标准哈希表。这包括所有符号,但 determine_info()代码过滤掉全部符号和弱符号:

<$ ((ELFW(ST_BIND)(symtab-> st_info)== STB_GLOBAL
91 || ELFW(ST_BIND)(symtab-> st_info)== STB_WEAK)(p $ p>

为了表示Objective-C函数地址,您必须自己执行查找,而不是过滤出本地函数符号,并且必须将Objective-C函数符号去映射以将 _c_TheObject ___ printTrace 还原为 + [TheObject _printTrace]


Update: I'm working with the GNU-runtime on Linux. The problem does not occur on MacOS with the Apple-runtime.

Update 2: I compiled the GNU-runtime on MacOS and build the example with it. The error does not occur on MacOS with the GNU-runtime. I would say the problem is the glibc (since backtrace and backtrace_symbols are glibc extensions).

When printing a backtrace in a GCC compiled Objective-C app using backtraceand backtrace_symbols, I don't get any Objective-C symbols. Only the filenames, addresses and C-symbols appear.

I compiled with -g and linked with -rdynamic.

My test app:

void _printTrace()
{
    void *addr[1024];
    int aCount = backtrace(addr, 1024);
    char **frameStrings = backtrace_symbols(addr, aCount);
    for (int i = 0; i < aCount; i++) {
        printf("%s\n", frameStrings[i]);
    }
    free(frameStrings);
}

@interface TheObject
+ (void)_printTrace;
+ (void)printTrace;
@end

@implementation TheObject
+ (void)_printTrace
{
    _printTrace();
}

+ (void)printTrace
{
    [self _printTrace];
}
@end

void printTrace()
{
    [TheObject printTrace];
}

int main(int argc, char **argv)
{
    printTrace();
    return 0;
}

and it's output:

./test.bin(_printTrace+0x1f) [0x8048e05]
./test.bin() [0x8048e60]
./test.bin() [0x8048e8b]
./test.bin(printTrace+0x34) [0x8048ec5]
./test.bin(main+0xf) [0x8048eda]
/lib/libc.so.6(__libc_start_main+0xe5) [0xb7643bb5]
./test.bin() [0x8048b51]

Is there a way to let the Objective-C symbols appear in this backtrace?

解决方案

dladdr() only reports global and weak symbols. But all Objective-C function symbols are local:

$ readelf -s so_backtrace

Symbol table '.dynsym' contains 29 entries:
…

Symbol table '.symtab' contains 121 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
…
    49: 08048a01    13 FUNC    LOCAL  DEFAULT   14 _c_TheObject___printTrace
    50: 08048a0e    47 FUNC    LOCAL  DEFAULT   14 _c_TheObject__printTrace
…

You can verify that local symbols are never returned by looking at the GNU libc source code yourself. backtrace_symbols() is defined in sysdeps/generic/elf/backtracesyms.c. It relies on _dl_addr(), which is defined in elf/dl-addr.c, to provide it with the symbol names. That ultimately calls determine_info(). If it can, it uses the the GNU hash table, which does not include local symbols by design:

49       /* We look at all symbol table entries referenced by the hash
50          table.  */
…
60                   /* The hash table never references local symbols so
61                      we can omit that test here.  */

If the GNU hash table isn't present, it falls back to standard hash table. This includes all the symbols, but the determine_info() code filters out all but the global symbols and weak symbols:

90         if ((ELFW(ST_BIND) (symtab->st_info) == STB_GLOBAL
91              || ELFW(ST_BIND) (symtab->st_info) == STB_WEAK)

To symbolicate the Objective-C function addresses, you would have to perform the look-up yourself and not filter out the local function symbols. Further, you would have to demangle the Objective-C function symbols to restore _c_TheObject___printTrace to +[TheObject _printTrace].

这篇关于为什么回溯不包含Objective-C符号而不管-rdynamic?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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