在OS X上以编程方式在共享库中查找本地符号的偏移量 [英] Finding Offsets of Local Symbols in Shared Libraries Programmatically on OS X

查看:146
本文介绍了在OS X上以编程方式在共享库中查找本地符号的偏移量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在OS X的共享库中找到本地符号的偏移量.本地符号与未导出的符号一样.因此dyld("symbol_name")将不起作用.

I need to find the offset of a local symbol in a shared library on OS X. Local symbol as in non-exported symbol. Therefore dyld("symbol_name") will not work.

但是我可以使用nm查找这些偏移量,例如

I can however use nm to find these offsets, for example

$ nm /System/Library/PrivateFrameworks/DesktopServicesPriv.framework/DesktopServicesPriv  | grep -e ChildSetLabel -e NodeVolumeEject
000000000006cccd T _NodeVolumeEject
000000000009dbd7 t __ChildSetLabel

在这里我们看到了导出的(T)符号NodeVolumeEject,它的偏移量0x6cccd我可以使用dyld("NodeVolumeEject")轻松显示. dyld()将显示当前地址空间中的地址,但是我对共享库中的偏移量或地址空间中的绝对地址感到满意.此外,还有本地符号(t)_ChildSetLabel,它是偏移量(0x9dbd7),我无法使用dyld()来显示.

There we see the exported (T) symbol NodeVolumeEject which's offset 0x6cccd I can easily reveal using dyld("NodeVolumeEject"). dyld() will reveal the address in the current address space but I'm happy with either the offset in the shared library or the absolute address in the address space. Additionally, there's the local (t) symbol _ChildSetLabel which's offset (0x9dbd7) I cannot reveal using dyld().

我希望能够以编程方式进行此解析(没有gobjdumpnmotool或任何其他外部程序).是否有简单"的方法来实现这一目标?上面提到的工具的源代码包含所需的代码,但我想知道是否没有更简单的方法.

I'd like to be able to do this resolution programmatically (without gobjdump, nm, otool, or any other external program). Is there an "easy" way to achieve that? The source code of the tools mentioned above contains the needed code but I wonder if there isn't something more straightforward.

域:该解决方案仅适用于x86_64 MachO二进制文件的OS X 10.8或更高版本.

Domain: The solution has only to work on OS X 10.8 or better for x86_64 MachO binaries.

澄清:我很乐意弄清楚当前偏移量中的绝对偏移量(由于ASLR)显然不是静态的.但是我也很高兴找出相对于该库开始的偏移量,该偏移量保持静态(直到重新编译).从库中的地址"到地址空间中的地址"的部分非常简单:

Clarification: I would be happy to figure out the absolute offset in the current offset (which due to ASLR) is not static obviously. But I'm also happy to figure out the offset relative to the start of that library, which remains static (until recompile). The part from "address in the library" to "address in the address space" is quite easy:

off_t sym_offset_child_set_label = ANSWER_TO_THIS_QUESTION("_ChildSetLabel");
Dl_info info;
void *abs_volume_eject = dlsym(RTLD_DEFAULT, "NodeVolumeEject");
void *abs_child_set_label = NULL;
if (dladdr(abs_volume_eject, &info)) {
    abs_child_set_label = (void *)((char *)info.dli_fbase + sym_offset_child_set_label);

    /* abs_child_set_label now points to the function in question */
}

只要_ChildSetLabelNodeVolumeEject在同一个共享库中,就足够了.因此,ASLR在这里不是问题.

This is, as long as _ChildSetLabel and NodeVolumeEject are in the same shared library enough. Therefore, ASLR is not an issue here.

推荐答案

另一种可能性(我最终使用的是苹果的私有CoreSymbolication框架):

Another possibility (what I ended up using) is Apple's private CoreSymbolication framework:

void *resolve_private(const char *symbol_owner, const char *symbol_to_resolve)
{
    task_t targetTask;
    int err = task_for_pid(mach_task_self(), getpid(), &targetTask);
    if (err) {
        fprintf(stderr, "couldn't get my Mach task\n");
        return NULL;
    }

    CSSymbolicatorRef targetSymbolicator;

    targetSymbolicator = CSSymbolicatorCreateWithTaskFlagsAndNotification(targetTask,
                                                                              kCSSymbolicatorTrackDyldActivity,
                                                                          ^(uint32_t     notification_type, CSNotificationData data) {
                                                                          });
    if(CSIsNull(targetSymbolicator)) {
        fprintf("CSSymbolicatorCreateWithTaskFlagsAndNotification failed\n");
        return NULL;
    }

    __block CSSymbolOwnerRef symbolOwner = kCSNull;
    CSSymbolicatorForeachSymbolOwnerWithNameAtTime(targetSymbolicator,
                                                   symbol_owner,
                                                   kCSNow,
                                                   ^(CSSymbolOwnerRef owner) {
                                                       symbolOwner = owner;
                                                   });
    if (CSIsNull(symbolOwner)) {
        CSRelease(targetSymbolicator);
        fprintf("CSSymbolicatorForeachSymbolOwnerWithNameAtTime failed\n");
        return NULL;
    }

    __block uintptr_t p = (uintptr_t)NULL;
    CSSymbolOwnerForeachSymbol(symbolOwner, ^(CSSymbolRef symbol) {
        const char *symbol_name = CSSymbolGetMangledName(symbol);
        if (0 == strcmp(symbol_name, symbol_to_resolve)) {
            p = CSSymbolGetRange(symbol).location;
        }
    });

    CSRelease(targetSymbolicator);
    if ((uintptr_t)NULL == p) {
        fprintf("symbol not found\n");
        return NULL;
    } else {
        return (void *)p;
    }
}

这篇关于在OS X上以编程方式在共享库中查找本地符号的偏移量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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