2010-10-12 20 views
33

¿Cómo funcionan los puntos de interrupción en el código C++? ¿Se insertan instrucciones especiales entre algunas instrucciones del ensamblador cuando se compila el código? ¿O hay algo más en su lugar? Además, ¿cómo se implementa el paso a través del código? De la misma manera que los puntos de interrupción ...?¿Cómo funcionan los puntos de interrupción en el código C++?

+0

Los puntos de interrupción se inyectan dinámicamente por el depurador en el tiempo de ejecución del proceso. Y yo esperaría que esto también cuente para recorrer el código. Sin embargo, no soy 100% positivo sobre esto. – Vinzenz

+0

@gablin, ¿te importaría si editamos la pregunta para preguntar sobre el código "nativo" en lugar de "C++"? Es el mismo problema y refleja mejor las respuestas que tienes. –

+0

@StevenFisher: No, adelante. =) – gablin

Respuesta

35

Esto depende mucho de la CPU y del depurador.

Por ejemplo, una de las posibles soluciones en x86 CPU:

  • Insertar un byte de instrucción INT3 en el lugar requerido
  • Esperar hasta que la excepción punto de interrupción golpea
  • Compare dirección de excepción a la lista de punto de interrupción para determinar cuál
  • Realizar acciones de punto de interrupción
  • Reemplazar INT3 con el byte original y cambiar el proceso depurado al modo de seguimiento (ejecución paso a paso de la CPU i) recauciones)
  • Continuar depurado proceso
  • Inmediatamente se captura una excepción rastro - la instrucción se ejecuta
  • INT3 Poner de nuevo

puntos de observación se pueden implementar de forma similar, pero en lugar de INT3 te ponen la memoria página donde la variable observada está en solo lectura, o en modo sin acceso, y espera la excepción de segmentación.

El escalonamiento del ensamblaje también se puede realizar utilizando el modo de trazado. Pasar por las líneas de origen también se puede hacer colocando puntos de interrupción en las siguientes instrucciones, en función de los datos de depuración.

También algo de CPU tiene soporte de punto de interrupción de hardware, cuando simplemente carga la dirección en algún registro.

+0

No entiendo la parte "reemplazar INT3 con byte original" ... ¿Por qué tenemos que hacer esto? – gablin

+0

Después de reanudar desde el punto de interrupción, debe ejecutar las instrucciones de la CPU donde se detuvo, pero lo corrompió: reemplazó el primer byte con el código de operación INT3. Entonces necesita restaurarlo, dejar que la instrucción sea procesada por la CPU, y luego volver a poner INT3, para que la próxima vez que se ejecute esta instrucción, se rompa nuevamente – Xeor

+1

Oh, ya veo. Entonces, así es como el depurador "inyecta" los puntos de interrupción en el código. ¡Gracias! – gablin

8

Según this blog entry en technochakra.com que son correctas: los puntos de interrupción

software funcionan mediante la inserción de una instrucción especial en el programa que se está depurando. Esta instrucción especial en la plataforma Intel es "int 3". Cuando se ejecuta, llama al controlador de excepción del depurador.

No obstante, no estoy seguro de cómo implementar las siguientes instrucciones. Sin embargo, el artículo continúa agregando:

Por razones prácticas, no es prudente solicitar una recompilación cada vez que se agregue o elimine un punto de interrupción. Los depuradores cambian la imagen cargada del ejecutable en la memoria e insertan la instrucción "int 3" en el tiempo de ejecución.

Sin embargo, esto solo se usaría para la opción "ejecutar a la línea actual".

4

El paso único se implementa en el nivel de código (ensamblador) no en el nivel C++. El depurador sabe cómo asignar las líneas de código de C++ a las direcciones de código.

Existen diferentes implementaciones. Hay CPU que soportan la depuración con registros de punto de interrupción. Cuando la ejecución alcanza la dirección en el registro de punto de interrupción, la CPU ejecuta una excepción de punto de interrupción.

Un enfoque diferente es parchear el código para el momento de la ejecución con una instrucción especial, en el mejor de una instrucción de un byte. En los sistemas x86 que usualmente son int 3.

El primer enfoque permite puntos de interrupción en ROM, el segundo permite más puntos de interrupción al mismo tiempo.

1

AFAIK Todos los depuradores (para cualquier lenguaje compilado) que permiten un número ilimitado de puntos de interrupción usan una variante de reemplazar la instrucción para ser breakpoint con un valor especial (como se describió anteriormente) y mantener una lista de lugares donde estos valores han sido metido.

Cuando el procesador intenta ejecutar uno de estos valores especiales, se genera una excepción, el depurador lo detecta y comprueba si la dirección de la excepción se encuentra en su lista de puntos de interrupción. Si lo es, se invoca el depurador y se le da al usuario la oportunidad de interactuar. Si no lo es, entonces la excepción se debe a algo que estaba en el programa desde el principio y el depurador permite que la excepción 'pase' a cualquier controlador de errores que pueda existir.

Tenga en cuenta también, que el código de auto-modificación de depuración puede fallar precisamente porque el depurador modifica momentáneamente el código en sí. (Por supuesto, nadie escribiría auto modificantes, ¿lo harían ahora?> ;-)

Por estas razones, es importante que el depurador tenga la oportunidad de eliminar todos los puntos de interrupción que establece antes de finalizar la sesión de depuración .

+0

"es importante que el depurador tenga la oportunidad de eliminar todos los puntos de interrupción que establece antes de finalizar la sesión de depuración". Nah: el depurador solo modifica la imagen en la memoria, no el archivo original en el disco. –

+0

De hecho, pero si finaliza el depurador y deja que el programa continúe, debe eliminar los puntos de interrupción en memoria antes de dejar que el programa vaya al – smirkingman

+0

¿Qué pasa si el código de su programa es más grande que su memoria? Tal vez gdb use mmap con MAP_PRIVATE para evitar que los puntos de interrupción penetren en el disco ... –

Cuestiones relacionadas