Domanda

Voglio essere in grado di rilevare quando si verifica un indirizzo di scrittura in memoria, ad esempio impostando un callback collegato a un interrupt. Qualcuno sa come?

Mi piacerebbe poterlo fare in fase di esecuzione (forse gdb ha questa funzione, ma il mio particolare l'applicazione causa l'arresto anomalo di gdb).

È stato utile?

Soluzione

Se si desidera intercettare le scritture in un intervallo di indirizzi, è possibile utilizzare mprotect ( ) per contrassegnare la memoria in questione come non scrivibile e installare un gestore di segnale usando sigaction () per catturare il SIGSEGV risultante, eseguire la registrazione o altro e contrassegnare nuovamente la pagina come scrivibile.

Altri suggerimenti

Ciò di cui hai bisogno è l'accesso ai registri di debug X86: http://en.wikipedia.org/wiki / Debug_register

Dovrai impostare l'indirizzo del breakpoint in uno di DR0 su DR3, quindi la condizione (scrittura dei dati) in DR7. Si verificherà l'interruzione e sarà possibile eseguire il codice di debug per leggere DR6 e trovare ciò che ha causato il punto di interruzione.

Se GDB non funziona, potresti provare un debugger più semplice / più piccolo come http: // sourceforge. net / projects / minibug / - se non funziona, puoi almeno esaminare il codice e capire come usare tu stesso l'hardware di debug sul processore.

Inoltre, esiste una grande risorsa per sviluppatori IBM sulla padronanza delle tecniche di debug di Linux che dovrebbe fornire alcune opzioni aggiuntive:

http://www.ibm.com/developerworks/linux/library / l-debug /

Un articolo abbastanza buono su questo è Windows è qui (so che stai funzionando su Linux, ma altri potrebbero venire a questa domanda che vogliono farlo su Windows):

http://www.codeproject.com/KB/debug/hardwarebreakpoint.aspx

-Adam

GDB ha questa funzione: si chiama watchpoint hardware ed è molto ben supportato su Linux / x86:

(gdb) watch *(int *)0x12345678

Se l'applicazione interrompe il GDB, crea l'attuale GDB da CVS Head .

Se il GDB non riesce ancora, presentare un GDB bug .

È probabile che possiamo correggere GDB più velocemente di quanto tu possa hackerare con il gestore SIGSEGV (fornito un buon caso di test) e correzioni a GDB ti aiutano anche con problemi futuri.

mprotect ha uno svantaggio: la tua memoria deve essere allineata al limite della pagina. Avevo la mia memoria problematica nello stack e non ero in grado di usare mprotect ().

Come ha detto Adam, quello che vuoi è manipolare i registri di debug. Su Windows, ho usato questo: http://www.morearty.com/code/breakpoint/ e ha funzionato benissimo. L'ho anche portato su Mach-O (Mac OS X) e ha funzionato alla grande. È stato anche facile, perché Mach-O ha thread_set_state (), che equivale a SetThreadContext ().

Il problema con Linux è che non ha simili equivalenti. Ho trovato ptrace, ma ho pensato, non può essere, deve esserci qualcosa di più semplice. Ma non c'è. Ancora. Penso che stiano lavorando su un'API hw_breakpoint sia per il kernel che per lo spazio utente. (vedi http://lwn.net/Articles/317153/ )

Ma quando l'ho trovato: http://blogs.oracle.com/nike/entry / memory_debugger_for_linux Ci ho provato e non era poi così male. Il metodo ptrace funziona con alcuni "processi esterni" fungendo da "debugger", collegandosi al programma, immettendo nuovi valori per i registri di debug e terminando con il programma continuando con un nuovo set di punti di interruzione hw. Il fatto è che puoi creare questo "processo esterno" te stesso usando fork (), (non ho avuto successo con un pthread) e facendo questi semplici passaggi in linea nel tuo codice.

Il codice addwatchpoint deve essere adattato per funzionare con Linux a 64 bit, ma questo sta cambiando USER_DR7 ecc. in offsetof (struct user, u_debugreg [7]). Un'altra cosa è che dopo un PTRACE_ATTACH, devi aspettare che il debuggee si fermi effettivamente. Ma invece di riprovare un POKEUSER in un circuito affollato, la cosa giusta da fare sarebbe un waitpid () sul tuo pid.

L'unico problema con il metodo ptrace è che il tuo programma può avere solo un "debugger" attaccato alla volta. Quindi un ptrace attach fallirà se il tuo programma è già in esecuzione sotto controllo gdb. Ma proprio come il codice di esempio, è possibile registrare un gestore di segnale per SIGTRAP, eseguire senza gdb e quando si rileva il segnale, immettere un loop occupato in attesa che gdb si colleghi. Da lì puoi vedere chi ha provato a scrivere la tua memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top