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?
risposta
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.
Dovresti dire la versione del kernel invece della semplice data :-) –
__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
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
funziona ancora solo su x86? – Damian
Questo va bene per gli IDE MS, ma cosa succede se sto usando Eclipse e GCC? – Mawg
Ahh, ho capito, mi dispiace. Ho dovuto smascherare le pagine per l'esecuzione. Int 3 è ancora una trappola debug valida.
Dettagli? Le menti curiose vorrebbero sapere. – BeeOnRope
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
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). –
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.
Quale SO/versione? –