2013-07-03 41 views
7

Tôi cần tìm offset của biểu tượng cục bộ trong thư viện được chia sẻ trên OS X. Biểu tượng cục bộ như trong biểu tượng không được xuất. Do đó dyld("symbol_name") sẽ không hoạt động.Tìm offset của các ký hiệu cục bộ trong các thư viện chia sẻ Lập trình trên OS X

Tôi tuy nhiên có thể sử dụng nm để tìm những offsets, ví dụ

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

Có chúng ta thấy xuất khẩu (T) biểu tượng NodeVolumeEject mà bù đắp 0x6cccd tôi có thể dễ dàng tiết lộ sử dụng dyld("NodeVolumeEject"). dyld() sẽ tiết lộ địa chỉ trong không gian địa chỉ hiện tại nhưng tôi hài lòng với việc bù đắp trong thư viện được chia sẻ hoặc địa chỉ tuyệt đối trong không gian địa chỉ. Ngoài ra, có biểu tượng địa phương (t) _ChildSetLabel độ lệch (0x9dbd7) Tôi không thể tiết lộ sử dụng dyld().

Tôi muốn có thể thực hiện độ phân giải này theo chương trình (không có gobjdump, nm, otool hoặc bất kỳ chương trình bên ngoài nào khác). Có cách nào "dễ" để đạt được điều đó không? Mã nguồn của các công cụ được đề cập ở trên chứa mã cần thiết nhưng tôi tự hỏi nếu không có gì đơn giản hơn.

Tên miền: Giải pháp chỉ hoạt động trên OS X 10.8 trở lên cho x86_64 MachO nhị phân.

Làm rõ: Tôi rất sẵn lòng tìm ra độ lệch tuyệt đối trong bù đắp hiện tại (do ASLR) không rõ ràng là tĩnh. Nhưng tôi cũng rất vui khi tìm ra độ lệch tương đối so với phần bắt đầu của thư viện đó, vẫn còn tĩnh (cho đến khi biên dịch lại). Phần từ "địa chỉ trong thư viện" đến "địa chỉ trong không gian địa chỉ" là khá dễ dàng:

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

Đây là, miễn là _ChildSetLabelNodeVolumeEject đang ở trong thư viện chia sẻ cùng đủ. Do đó, ASLR không phải là một vấn đề ở đây.

Trả lời

4

Một khả năng khác (những gì tôi đã kết thúc sử dụng) là tin CoreSymbolication khuôn khổ của Apple:

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; 
    } 
}