【问题标题】:Finding Offsets of Local Symbols in Shared Libraries Programmatically on OS X在 OS X 上以编程方式查找共享库中本地符号的偏移量
【发布时间】:2013-07-01 00:33:24
【问题描述】:

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

【问题讨论】:

    标签: macos shared-libraries mach-o dyld


    【解决方案1】:

    另一种可能性(我最终使用的)是 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 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;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-11-27
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      • 2015-01-13
      • 1970-01-01
      • 2017-08-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多