在OS X上以编程方式查找共享库中局部符号的偏移量

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

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

$ 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()

我希望能够以编程方式执行此解析(不使用gobjdumpnmotool或任何其他外部程序)。 有没有一种“简单”的方法来实现这一目标? 上面提到的工具的源代码包含了所需的代码,但我想知道是否没有更直接的东西。

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

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

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在这里不是问题。


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

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 taskn");
        return NULL;
    }

    CSSymbolicatorRef targetSymbolicator;

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

    __block CSSymbolOwnerRef symbolOwner = kCSNull;
    CSSymbolicatorForeachSymbolOwnerWithNameAtTime(targetSymbolicator,
                                                   symbol_owner,
                                                   kCSNow,
                                                   ^(CSSymbolOwnerRef owner) {
                                                       symbolOwner = owner;
                                                   });
    if (CSIsNull(symbolOwner)) {
        CSRelease(targetSymbolicator);
        fprintf("CSSymbolicatorForeachSymbolOwnerWithNameAtTime failedn");
        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 foundn");
        return NULL;
    } else {
        return (void *)p;
    }
}
链接地址: http://www.djcxy.com/p/72455.html

上一篇: Finding Offsets of Local Symbols in Shared Libraries Programmatically on OS X

下一篇: How to get boost::system::error