Finding Offsets of Local Symbols in Shared Libraries Programmatically on OS X

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.

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

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

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.

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

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 */
}

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


另一种可能性(我最终使用的)是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/72456.html

上一篇: 使用X509证书对多个收件人进行XML加密和解密

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