Pregunta

Quiero poder detectar cuándo se produce una escritura en la dirección de la memoria, por ejemplo, configurando una devolución de llamada asociada a una interrupción. ¿Alguien sabe cómo?

Me gustaría poder hacer esto en tiempo de ejecución (posiblemente gdb tiene esta función, pero mi particular la aplicación hace que gdb se bloquee).

¿Fue útil?

Solución

Si desea interceptar escrituras en un rango de direcciones, puede usar mprotect ( ) para marcar la memoria en cuestión como no grabable, e instalar un controlador de señales usando sigaction () para capturar el SIGSEGV resultante, haga su registro o lo que sea y marque la página como grabable nuevamente.

Otros consejos

Lo que necesita es acceso a los registros de depuración de X86: http://en.wikipedia.org/wiki / Debug_register

Deberá establecer la dirección del punto de interrupción en uno de DR0 a DR3 y luego la condición (escritura de datos) en DR7. Se producirá la interrupción y puede ejecutar su código de depuración para leer el DR6 y encontrar la causa del punto de interrupción.

Si GDB no funciona, puede probar un depurador más simple / pequeño como http: // sourceforge. net / projects / minibug / : si eso no funciona, al menos puede revisar el código y entender cómo usar el hardware de depuración en el procesador.

También, hay un gran recurso para desarrolladores de IBM sobre el dominio de las técnicas de depuración de Linux que debería proporcionar algunas opciones adicionales:

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

Un artículo razonablemente bueno sobre cómo hacer esto es windows está aquí (sé que estás ejecutando Linux, pero otros podrían venir a esta pregunta con ganas de hacerlo en windows):

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

-Adam

GDB tiene esa característica: se llama puntos de control de hardware y está muy bien soportado en Linux / x86:

(gdb) watch *(int *)0x12345678

Si su aplicación bloquea GDB, compile GDB actual desde CVS Head . / p>

Si el GDB sigue fallando, presente un error de GDB.

Lo más probable es que podamos reparar el GDB más rápido de lo que puede piratear el controlador SIGSEGV (siempre que sea un buen caso de prueba), y las correcciones a GDB también lo ayudan con problemas futuros.

mprotect tiene una desventaja: su memoria debe estar alineada con el límite de la página. Tenía mi memoria problemática en la pila y no pude usar mprotect ().

Como dijo Adam, lo que se quiere es manipular los registros de depuración. En Windows, utilicé esto: http://www.morearty.com/code/breakpoint/ y funcionó muy bien. También lo porté a Mach-O (Mac OS X), y funcionó muy bien, también. También fue fácil, porque Mach-O tiene thread_set_state (), que es equivalente a SetThreadContext ().

El problema con Linux es que no tiene tales equivalentes. Encontré ptrace, pero pensé, esto no puede ser, debe haber algo más simple. Pero no hay. Todavía. Creo que están trabajando en una API hw_breakpoint tanto para el kernel como para el espacio de usuario. (consulte http://lwn.net/Articles/317153/ )

Pero cuando encontré esto: http://blogs.oracle.com/nike/entry / memory_debugger_for_linux Lo intenté y no fue tan malo. El método ptrace funciona mediante algún " proceso externo " actuando como un " depurador " ;, adjuntando a su programa, inyectando nuevos valores para los registros de depuración, y terminando con su programa continuando con un nuevo conjunto de puntos de interrupción de hw. La cosa es que puedes crear este " proceso externo " usted mismo usando fork (), (no tuve éxito con un pthread), y siguiendo estos sencillos pasos en línea en su código.

El código addwatchpoint debe adaptarse para funcionar con Linux de 64 bits, pero eso es solo cambiar USER_DR7, etc., a offsetof (struct user, u_debugreg [7]). Otra cosa es que después de un PTRACE_ATTACH, tienes que esperar a que el debuggee se detenga realmente. Pero en lugar de volver a intentar con un POKEUSER en un bucle ocupado, lo correcto sería un waitpid () en tu pid.

El único problema con el método ptrace es que su programa solo puede tener un " depurador " adjunto a la vez. Por lo tanto, un adjunto ptrace fallará si su programa ya se está ejecutando bajo el control de gdb. Pero al igual que el código de ejemplo, puede registrar un controlador de señal para SIGTRAP, ejecutar sin gdb, y cuando detecte la señal, ingrese un bucle ocupado esperando que gdb se conecte. Desde allí puedes ver quién intentó escribir tu memoria.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top