2010-09-03 1 views
14

Nella programmazione in modalità a 32 bit, ho utilizzato molto il int 3 nei miei programmi per fermarsi in una determinata posizione con il debugger (incorporando le istruzioni nell'origine). Ora in 64 bit sembra non funzionare, producendo un SIGSEGV molto ordinario sotto gdb e distruggendo il programma oltre ogni speranza ("Programma terminato con segnale SIGSEGV, errore di segmentazione. Il programma non esiste più."). Mi chiedo se la modalità a 64 bit abbia un altro meccanismo, o se dovessi fare un po 'di cache-flush (lo int 3 è un codice operativo generato dinamicamente in questo caso (0xcc), è un codice simile a jit).Perché int 3 genera un SIGSEGV a 64 bit invece di arrestare il debugger?

+0

Quale SO/versione? –

risposta

7

BarsMonster's answer mostra che __asm__("int3"); non funziona su piattaforme a 64 bit. Questo è - almeno oggi (2014) - non vero.

Il seguente codice funziona su una piattaforma amd64:

punto di interruzione.c

int main() { 
    int i;  
    for(i=0; i<3;i++) { 
     __asm__("int3"); 
    } 
} 

compilarlo banalmente: gcc -c breakpoint.c e iniziare gdb a.out:

(gdb) run 
Starting program: /tmp/a.out 

Program received signal SIGTRAP, Trace/breakpoint trap. 
0x00000000004004fb in main() 

Vedete, gdb si ferma al punto di interruzione.

+2

Dovresti dire la versione del kernel invece della semplice data :-) –

20

__debugbreak()

Oggi un collega è venuto a chiedere come ottenere la funzionalità "int 3" le piattaforme a 64 bit. Cosa è "int 3"? È l'istruzione di assemblaggio che è utilizzata per creare un punto di interruzione. Almeno sono le istruzioni per il processore x86 e, come potete immaginare, lo è molto specifico della piattaforma.

Sulle piattaforme a 64 bit non è disponibile l'assemblaggio in linea , quindi il numero "__asm ​​int 3". Cosa fare adesso? Bene c'è un costrutto meno noto che è in realtà molto meglio usare in quello funziona su tutte le piattaforme (x64, Itanium e x86), che è __debugbreak(). Questo è un compilatore di Visual C++ intrinseco (definito in Visual C++ 2005 in vc \ include \ intrin.h, con tonnellate di altri interessanti intrinseci) che agirà effettivamente "int 3" su tutte le piattaforme.

DebugBreak, la funzione di chiamata Win32 è ancora in giro, ma in generale utilizzando __debugbreak() è la mia preferenza, se per nessun altro motivo che non è una chiamata di funzione (è un compilatore intrinseca), e don È necessario eseguire il debug dei simboli per ottenere uno stack di chiamata leggibile.

Se si scrive C++ che probabilmente non si vuole scrivere non portatile assemblaggio, e questo è solo uno in meno luogo in cui si sarebbe dovuto.

http://blogs.msdn.com/b/kangsu/archive/2005/09/07/462232.aspx

+9

Questa è una risposta molto informativa, ma come ho specificato nella mia domanda, stavo generando codice in modo dinamico, e questo esclude i componenti intrinseci del compilatore. Per non parlare del fatto che il mio solito compilatore non è Visual C++, né la mia piattaforma Windows. Inoltre, la risposta è inaccurata perché int 3 esiste e almeno a 64 bit Linux si comporta come al solito. Inoltre, a seconda del compilatore, si dispone di un assembly inline in modalità 64 bit. – dsign

+0

funziona ancora solo su x86? – Damian

+0

Questo va bene per gli IDE MS, ma cosa succede se sto usando Eclipse e GCC? – Mawg

10

Ahh, ho capito, mi dispiace. Ho dovuto smascherare le pagine per l'esecuzione. Int 3 è ancora una trappola debug valida.

+1

Dettagli? Le menti curiose vorrebbero sapere. – BeeOnRope

+0

Questa domanda era sette anni fa, quindi è difficile ricordare i dettagli di ciò che ho fatto. Ricordo che è stato abbastanza semplice, penso che stavo chiamando mmap (2) e ho appena aggiunto la bandiera PROT_EXEC. O era mprotect (2) ...? – dsign

+0

Probabilmente l'esecuzione non ha mai raggiunto il 'int3' perché il codice era in una pagina di lettura/scrittura/non-exec. Quindi il semplice salto lì ha causato un segfault, indipendentemente dal contenuto. E sì, 'PROT_READ | PROT_EXEC | PROT_WRITE' per mmap dovrebbe essere il giusto approccio. Oppure puoi iniziare con una pagina di lettura/scrittura, quindi girarla per leggere/exec con mprotect dopo aver finito, quindi non hai mai mappato una pagina di scrittura + exec (per motivi di sicurezza). –

0

Si consiglia di non utilizzare mai asm int 3 come funziona per tutti i tipi di build. Potresti dimenticare una riga da qualche parte nel tuo codice e questo può significare grossi problemi. L'alternativa è usare __debugbreak che è valido solo in modalità di debug.