2013-07-03 6 views
7

Muszę znaleźć offset miejscowym symbolem w udostępnionej biblioteki na OS X. Lokalnej jako symbol w niewyspecjalizowanych eksportowane symbolem. Dlatego dyld("symbol_name") nie będzie działać.Znalezienie Przesunięcia z symboli lokalnych w Shared Libraries programowo na OS X

mogę jednak użyć nm znaleźć te przesunięcia, na przykład

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

Nie widzimy eksportowane (T) symbol NodeVolumeEject który jest przesunięcie 0x6cccd mogę łatwo ujawniają wykorzystaniem dyld("NodeVolumeEject"). dyld() ujawni adres w aktualnej przestrzeni adresowej, ale jestem zadowolony z przesunięcia we wspólnej bibliotece lub z bezwzględnego adresu w przestrzeni adresowej. Dodatkowo istnieje lokalna (t) symbol _ChildSetLabel który jest przesunięcie (0x9dbd7) nie mogę ujawnić za pomocą dyld().

Chciałbym móc to zrobić programowo rozdzielczość (bez gobjdump, nm, otool ani żadnego innego zewnętrznego programu). Czy istnieje "łatwy" sposób, aby to osiągnąć? Kod źródłowy wyżej wymienionych narzędzi zawiera potrzebny kod, ale zastanawiam się, czy nie ma czegoś prostszego.

domeny: Rozwiązanie jest tylko do pracy na OS X 10.8 lub wyższy dla x86_64 macho plików binarnych.

Wyjaśnienie: Byłbym szczęśliwy, aby dowiedzieć się bezwzględna przesunięcie w prądzie offsetowego (które ze względu na ASLR) nie jest statyczna oczywiście. Ale cieszę się również z obliczenia przesunięcia w stosunku do początku tej biblioteki, która pozostaje statyczna (do ponownej kompilacji). Część z „adres w bibliotece” na „adres w przestrzeni adresowej” jest dość proste:

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

To, jak długo _ChildSetLabel i NodeVolumeEject są w tej samej wspólnej biblioteki wystarczy. Dlatego ASLR nie stanowi tutaj problemu.

Odpowiedz

4

Inna możliwość (co skończyło się używając) jest Apple prywatny CoreSymbolication ramy:

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