5

Ho incluso il tag iOS, ma sto eseguendo il simulatore su un Core i7 MacBook Pro (x86-64, giusto?), Quindi penso che sia irrilevante.Cosa contengono i contenuti dei registri di uso generale?

Attualmente eseguo il debug di un arresto anomalo negli annunci video di Flurry. Ho un punto di interruzione impostato sulle eccezioni Objective-C. Quando viene colpito il punto di interruzione, sono a objc_msgSend. Il callstack contiene un mix di metodi Flurry e iOS privati, niente di pubblico e niente di ciò che ho scritto. Chiamata register read dalle objc_msgSend uscite dello stack di trama che segue:

(lldb) register read 
General Purpose Registers: 
     eax = 0x1ac082d0 
     ebx = 0x009600b5 "spaceWillDismiss:interstitial:" 
     ecx = 0x03e2cddb "makeKeyAndVisible" 
     edx = 0x0000003f 
     edi = 0x0097c6f3 "removeWindow" 
     esi = 0x00781e65 App`-[FlurryAdViewController removeWindow] + 12 
     ebp = 0xbfffd608 
     esp = 0xbfffd5e8 
     ss = 0x00000023 
    eflags = 0x00010202 App`-[FeedTableCell setupVisibleCommentAndLike] + 1778 at FeedTableCell.m:424 
     eip = 0x049bd09b libobjc.A.dylib`objc_msgSend + 15 
     cs = 0x0000001b 
     ds = 0x00000023 
     es = 0x00000023 
     fs = 0x00000000 
     gs = 0x0000000f 

ho alcune domande su questa uscita.

  • Ho ipotizzato $ ebx contiene il selettore che ha causato l'arresto anomalo e $ edi è l'ultimo metodo di esecuzione. È questo il caso?
  • $ eip è dove sono andato in crash. Di solito è così?
  • $ eflags fa riferimento a un metodo di istanza che, per quanto ne so, non ha nulla a che fare con questo arresto anomalo. Cos'è quello?
  • C'è qualche altra informazione che posso fare su questi registri?

risposta

1

Non riesco a parlare specificamente ai layout di frame iOS/Objective-C, quindi non posso rispondere alla domanda su EBX e EDI. Ma posso aiutarti per quanto riguarda EIP ed EFLAGS e darti alcuni suggerimenti generali su ESP/EBP e sui registri di selezione. (A proposito, il simulatore sta simulando un ambiente x86 a 32-bit; si può dire perché i registri sono 32 bit di lunghezza.)

EIP è il registro instruction pointer, noto anche come il contatore di programma di, che contiene la indirizzo dell'istruzione macchina attualmente in esecuzione. Quindi indicherà dove il programma si è arrestato in modo anomalo, o più in generale, dove il programma si trova quando raggiunge un punto di interruzione, il core di scarico ecc.

EIP viene salvato e ripristinato per implementare le chiamate di funzione (a livello di codice macchina - inlining potrebbe causare chiamate di lingua di alto livello che non eseguono chiamate effettive). Nei linguaggi non sicuri della memoria, un overflow del buffer dello stack può sovrascrivere il valore salvato del puntatore dell'istruzione, facendo in modo che l'istruzione di ritorno ritorni nel posto sbagliato. Se sei fortunato, il valore sovrascritto attiverà un segfault sul successivo recupero della memoria, ma il valore di EIP sarà arbitrario e inutile nel debug del problema. Se sei sfortunato, un hacker ha creato il nuovo EIP per puntare a codice utile, quindi molti ambienti usano "stack cookie" o "canarini" per rilevare queste sovrascritture prima di ripristinare l'EIP salvato/sovrascritto, nel qual caso il valore EIP potrebbe essere utile.

EFLAGS non è un indirizzo di memoria, e probabilmente non è un registro di uso generale. Ogni bit di EFLAGS è un flag che può essere impostato o testato con varie istruzioni. I flag più importanti sono i flag carry, zero e sign, che sono impostati mediante istruzioni aritmetiche e utilizzati per la ramificazione condizionale. Il debugger lo interpreta erroneamente come un indirizzo di memoria e lo visualizza come la funzione più vicina, ma non è in realtà correlato al crash. (Lo + 1778 è il giveaway: questo significa EFLAGS punti 1778 byte nella funzione, ma è improbabile che la funzione sia effettivamente lunga 1778 byte.)

ESP è il puntatore dello stack e EBP è (di solito) il puntatore del frame (anche chiamato il puntatore di base). Questi registri hanno limitato il frame corrente allo stack di chiamate. Il tuo debugger di solito può mostrare i valori delle variabili di stack e lo stack di chiamate corrente in base a questi puntatori. In caso di danneggiamento, a volte è possibile ispezionare manualmente lo stack per recuperare EBP e srotolare manualmente lo stack di chiamate.Si noti che il codice può essere compilato senza puntatori di frame (omissione del puntatore del frame), liberando EBP per altri usi; questo è comune su x86 perché ci sono così pochi registri generici.

SS, CS, DS, ES, FS e GS detengono selettori di segmento, utilizzati nei vecchi giorni precedenti alla paginazione per implementare segmentation. Oggi FS e GS sono comunemente usati dai sistemi operativi per blocchi di stato di processo e di thread; erano gli unici registri selettori riportati in x86-64. I registri selettori generalmente non sono utili per il debug.

Problemi correlati