2010-09-03 16 views
14

En la programación en modo de 32 bits solía emplear int 3 en mis programas para detenerme en una ubicación determinada con el depurador (incrustando la instrucción en la fuente). Ahora en 64 bits parece no estar funcionando, produciendo un SIGSEGV muy ordinario bajo gdb y destruyendo el programa más allá de la esperanza ("Programa terminado con señal SIGSEGV, falla de segmentación. El programa ya no existe"). Me pregunto si el modo de 64 bits tiene otro mecanismo, o si debería hacer un cache-flush (el int 3 es un código de operación generado dinámicamente en este caso (0xcc), es un código similar a un jit).¿Por qué int 3 genera un SIGSEGV en 64 bits en lugar de detener el depurador?

+0

¿Qué sistema operativo/versión? –

Respuesta

7

La respuesta de BarsMonster muestra que __asm__("int3"); no funcionará en plataformas de 64 bits. Esto es, al menos hoy (2014), no es cierto.

El siguiente código trabajará en una plataforma amd64:

punto de interrupción.c

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

compilarlo trivialmente: gcc -c breakpoint.c y empezar gdb a.out:

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

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

Ves, GDB se detiene en el punto de interrupción.

+2

Debería decir la versión del kernel en lugar de la fecha :-) –

+1

@CiroSantilli 视 事件 视 视 视 视 Buen punto. Lamentablemente, no puedo decir nada más. Lo único que seguramente sé es que era un núcleo 3.x.y. Mi kernel actual es 3.19.0 y todavía funciona. – hek2mgl

20

__debugbreak()

Hoy en día un colega vino a preguntar acerca de cómo conseguir "int 3" funcionalidad en las plataformas de 64 bits. ¿Qué es "int 3"? Es la instrucción de ensamblaje que es que se usa para crear un punto de interrupción. Al menos que es la instrucción para el procesador x86 , y como se puede imaginar, es muy específico de la plataforma.

En las plataformas de 64 bits no hay ensamblado en línea , así que ahí va su "__asm ​​int 3". ¿Qué hacer ahora? Bueno, hay una construcción menos conocida que es mucho mejor para usar en ese funciona en todas las plataformas (x64, Itanium y x86), que es __debugbreak(). Este es un compilador de Visual C++ intrínseco (definido en Visual C++ 2005 en vc \ include \ intrin.h, con toneladas de otros intrínsecos geniales) que actuará efectivamente como "int 3" en todas las plataformas.

DebugBreak, la llamada a la función Win32 es todavía alrededor, pero en general el uso de __debugbreak() es mi preferencia, si no por otra razón que no es una llamada función (que es un compilador intrínseca), y don No es necesario depurar los símbolos para obtener una pila de llamadas legible.

Si estás escribiendo C++ es probable que no desea escribir no portátil ensamblaje , y esto es sólo uno menos lugar donde tendría que.

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

+9

Esta es una respuesta muy informativa, pero como especifiqué en mi pregunta, estaba generando código dinámicamente, y eso excluye los intrínsecos del compilador. Sin mencionar que mi compilador habitual no es Visual C++, ni mi plataforma Windows. Además, la respuesta es inexacta porque int 3 existe y al menos en 64 bits, Linux se comporta como siempre. Además, dependiendo del compilador, tiene ensamblado en línea en el modo de 64 bits. – dsign

+0

solo funciona en x86? – Damian

+0

Eso está bien para MS IDEs, pero ¿qué sucede si uso Eclipse y GCC? – Mawg

10

Ahh, lo tengo, lo siento. Tuve que desproteger las páginas para su ejecución. Int 3 sigue siendo una trampa de depuración válida.

+1

Detalles? A las mentes inquisitivas les gustaría saber. – BeeOnRope

+0

Esta pregunta fue hace siete años, por lo que es difícil recordar los detalles de lo que hice. Recuerdo que fue bastante sencillo, creo que estaba llamando a mmap (2) y acabo de agregar la bandera PROT_EXEC. ¿O era mprotect (2) ...? – dsign

+0

Es de suponer que la ejecución nunca llegó al 'int3' porque el código estaba en una página de lectura/escritura/no ejecución. Así que simplemente saltar allí provocó una segfault, independientemente de los contenidos. Y sí, 'PROT_READ | PROT_EXEC | PROT_WRITE' para mmap debería ser el enfoque correcto. O bien, podría comenzar con una página de lectura/escritura, luego voltearla para leer/exec con mprotect una vez que haya terminado, para que nunca tenga asignada una página de escritura + ejecutor (por razones de seguridad). –

0

Te recomiendo que nunca uses asm int 3 ya que funciona para todos los tipos de compilación. Es posible que olvide una línea en algún lugar de su código y eso puede significar grandes problemas. La alternativa es usar __debugbreak, que solo es válido en el modo de depuración.

Cuestiones relacionadas