2013-07-03 10 views
7

Devo trovare l'offset di un simbolo locale in una libreria condivisa su OS X. Simbolo locale come nel simbolo non esportato. Pertanto, dyld("symbol_name") non funzionerà.Ricerca offset di simboli locali nelle librerie condivise a livello di codice su OS X

posso però usare nm per trovare questi offset, ad esempio

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

Ci vediamo il (T) simbolo esportato NodeVolumeEject che ha compensato 0x6cccd posso facilmente rivelare usando dyld("NodeVolumeEject"). dyld() rivelerà l'indirizzo nello spazio degli indirizzi corrente ma sono contento dell'offset nella libreria condivisa o dell'indirizzo assoluto nello spazio degli indirizzi. Inoltre, c'è il simbolo locale (t) _ChildSetLabel che è offset (0x9dbd7) Non posso rivelare utilizzando dyld().

Mi piacerebbe essere in grado di fare questa risoluzione al livello di programmazione (senza gobjdump, nm, otool, o qualsiasi altro programma esterno). C'è un modo "facile" per raggiungerlo? Il codice sorgente degli strumenti di cui sopra contiene il codice necessario, ma mi chiedo se non c'è qualcosa di più semplice.

Dominio: la soluzione deve funzionare solo su OS X 10.8 o superiore per i binari di x86_64 MachO.

Chiarimento: sarei felice di capire l'offset assoluto nell'offset corrente (che a causa di ASLR) non è statico ovviamente. Ma sono anche felice di capire lo scostamento relativo all'inizio di quella libreria, che rimane statica (fino alla ricompilazione). La parte da "indirizzo nella biblioteca" a "indirizzo nello spazio di indirizzi" è abbastanza facile:

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

Questo è, a patto che _ChildSetLabel e NodeVolumeEject sono nella stessa libreria condivisa abbastanza. Pertanto, ASLR non è un problema qui.

risposta

4

Un'altra possibilità (quello che ho finito per usare) è privata CoreSymbolication quadro di 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; 
    } 
} 
Problemi correlati