2012-01-11 9 views
7

Sto cercando di capire come funzionano i file Mach-o, e ho fatto molti progressi con le risorse online disponibili (in particolare, la pagina Apple qui: http://developer.apple.com/library/mac/#documentation/developertools/conceptual/MachORuntime/Reference/reference.html), ma io hanno colpito un posto di blocco per capire come funzionano gli stub dei simboli.Mach-O symbol stubs (IOS)

Utilizzando "otool -l" Vedo la seguente sezione:

Section 
    sectname __symbolstub1 
    segname __TEXT 
     addr 0x00005fc0 
     size 0x00000040 
    offset 20416 
    align 2^2 (4) 
    reloff 0 
    nreloc 0 
    flags 0x80000408 

Tuttavia quando guardo i dati dal file binario in un editor esadecimale compaiono i seguenti 4 byte ripetuti più e più volte:

00005FC0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FD0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FE0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 
00005FF0 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 38 F0 9F E5 88 

Sembra simile a un LDR che aumenta il PC di una quantità fissa, ma non vedo perché l'importo è lo stesso per ogni voce nella tabella dei simboli.

Se qualcuno può far luce sul motivo per cui è così, o fornire risorse che ottengono questo livello basso, per favore fatemelo sapere.

Grazie!

+0

Penso di aver capito cosa sta succedendo, ciascuna delle voci a 4 byte nella tabella punta a un'area dati al di sotto della quale è presente un'istruzione DCD che memorizza la posizione della chiamata di funzione. Tuttavia, sono ancora un po 'confuso perché è richiesto questo livello aggiuntivo di indirizzamento, quindi se qualcuno può fornire informazioni di follow, lo apprezzerei. – Locksleyu

risposta

12

Descriverò la situazione con l'attuale iOS, è leggermente diverso nelle vecchie versioni.

Gli stub simbolo effettivamente caricano nel PC un puntatore di funzione. Per lo standard "artificiale" (on-demand) importazioni, il puntatore risiede nella sezione __lazy_symbol e inizialmente indica una routine helper nella sezione __stub_helper, ad esempio:

__symbolstub1 _AudioServicesAddSystemSoundCompletion 
__symbolstub1 LDR PC, _AudioServicesAddSystemSoundCompletion$lazy_ptr 
__symbolstub1 ; End of function _AudioServicesAddSystemSoundCompletion 

__lazy_symbol _AudioServicesAddSystemSoundCompletion$lazy_ptr DCD _AudioServicesAddSystemSoundCompletion$stubHelper 

__stub_helper _AudioServicesAddSystemSoundCompletion$stubHelper 
__stub_helper LDR R12, =nnn ; symbol info offset in the lazy bind table 
__stub_helper B dyld_stub_binding_helper 

La funzione dyld_stub_binding_helper è il pugno uno nel Sezione __stub_helper e in sostanza è solo un trampolino per la funzione dyld_stub_binder in dyld, passando ad esso quello che io chiamo valore "simbolo di offset delle informazioni". Tale valore è un offset all'interno del flusso di informazioni di binding lazy (indicato dal comando di caricamento LC_DYLD_INFO o LC_DYLD_INFO_ONLY), che è una sorta di flusso bytecode con comandi per dyld. sequenza tipica per un'importazione pigro è simile al seguente:

72: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB(M, 0xYYYYY) 
19: BIND_OPCODE_SET_DYLIB_ORDINAL_IMM(NNNN) 
40: BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM(0x00, '_AudioServicesAddSystemSoundCompletion') 
90: BIND_OPCODE_DO_BIND() 

qui dyld sarebbe effettuare le seguenti operazioni:

  1. guardare in alto funzione denominata '_AudioServicesAddSystemSoundCompletion' dal un numero dylib NNNN nella lista dei dylibs elencati il carico comandi .
  2. cercare il numero di segmento dell'eseguibile M (molto probabilmente __DATA)
  3. scrivere il puntatore di funzione sull'offset YYYYY.
  4. salto all'indirizzo guardato in modo che la funzione reale fa il suo lavoro

L'indirizzo scritto sembra essere lo slot _AudioServicesAddSystemSoundCompletion$lazy_ptr. Quindi, la volta successiva che viene chiamato il _AudioServicesAddSystemSoundCompletion, salterà direttamente alla funzione importata, senza passare da dyld.

N.B.: non dovresti guardare subito l'offset 05fc0 nel file. Il campo addr è l'indirizzo virtuale, dovresti cercare il comando del segmento che contiene e vedere in che cosa si avvia VA e quale è il suo offset di file, quindi fai i conti. Di solito il segmento __TEXT inizia a 1000.

Tuttavia, gli stub dei simboli effettivi sembrano incollati, probabilmente si ha un grasso mach-o con l'intestazione del grasso che prende i primi 1000 byte, quindi gli offset si allineano.

+0

+1. Applauso lento, standing ovation. Risposta fantastica Ho imparato molto da questo! – mattjgalloway

+0

Wow, risposta sorprendente! Devo leggerlo un paio di volte prima di poterlo capire appieno, ma Igor, per favore, dimmi una cosa. Dove hai preso questa conoscenza? Leggendo tutto l'ASM pertinente o è documentato completamente da qualche parte? Grazie! – Locksleyu

+0

Principalmente dai binari, sì. Comunque, in teoria puoi anche capirlo dal codice sorgente - vedi [Fonti di Apple] (http://opensource.apple.com/source/) per dyld, ld64 e Csu. –

Problemi correlati