2008-10-19 20 views
137

Me pregunto cómo funciona un depurador? Particularmente el que se puede 'adjuntar' al ejecutable que ya se ejecuta. Entiendo que el compilador traduce el código al lenguaje de la máquina, pero ¿cómo puede el depurador "saber" a qué se lo está adjuntando?¿Cómo funciona un depurador?

+4

El artículo de Eli se ha movido a http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1 – Oktalist

+0

@Oktalist Este artículo es interesante, pero solo habla sobre la abstracción de nivel API para depuración en Linux. Supongo que OP quiere saber más acerca de debajo del capó. – smwikipedia

Respuesta

74

Los detalles de cómo funciona un depurador dependerán de lo que se está depurando, y lo que es el sistema operativo. Para la depuración nativa en Windows, puede encontrar algunos detalles en MSDN: Win32 Debugging API.

El usuario le dice al depurador qué proceso asociar, ya sea por nombre o por ID de proceso. Si se trata de un nombre, el depurador buscará el ID del proceso e iniciará la sesión de depuración mediante una llamada al sistema; en Windows esto sería DebugActiveProcess.

Una vez adjuntado, el depurador ingresará un bucle de evento como en cualquier interfaz de usuario, pero en lugar de eventos provenientes del sistema de ventanas, el sistema operativo generará eventos basados ​​en lo que sucede en el proceso que se depura, por ejemplo, una excepción . Ver WaitForDebugEvent.

El depurador es capaz de leer y escribir la memoria virtual del proceso de destino, e incluso ajustar sus valores de registro a través de las API proporcionadas por el sistema operativo. Consulte la lista de debugging functions para Windows.

El depurador es capaz de utilizar la información de archivos de símbolos para traducir de direcciones a nombres de variables y localizaciones en el código fuente. La información del archivo de símbolo es un conjunto separado de API y no es una parte central del sistema operativo como tal. En Windows, esto es a través del Debug Interface Access SDK.

Si está depurando un entorno administrado (.NET, Java, etc.) el proceso generalmente se verá similar, pero los detalles son diferentes, ya que el entorno de máquina virtual proporciona la API de depuración en lugar del sistema operativo subyacente.

+3

Esta pregunta puede sonar estúpida, pero ¿cómo hace el sistema operativo para realizar un seguimiento si se llega a una dirección específica dentro del programa? P.ej. un punto de interrupción se establece en la dirección 0x7710cafe. A medida que el puntero de instrucción cambia el sistema operativo (o tal vez la CPU) tendrá que comparar el puntero de instrucción con todas las direcciones de punto de interrupción, ¿o estoy equivocado? Como funciona esto ..? – displayname

+2

@StefanFalk Escribí [una respuesta] (http://stackoverflow.com/a/21746853/119527) que aborda algunos de los detalles de nivel inferior (en x86). –

+0

Gracias por la sugerencia :) – displayname

1

Mi entendimiento es que cuando se compila un archivo de aplicación o DLL, lo que se compila en contiene símbolos que representan las funciones y las variables.

Cuando se tiene una versión de depuración, estos símbolos son mucho más detalladas que cuando es una versión de lanzamiento, permitiendo así que el depurador para darle más información. Cuando adjuntas el depurador a un proceso, busca a qué funciones se está accediendo actualmente y resuelve todos los símbolos de depuración disponibles desde aquí (ya que sabe cómo se ve el interior del archivo compilado, puede acertar lo que podría estar en la memoria , con contenido de ints, flotadores, cuerdas, etc.). Al igual que el primer cartel, esta información y cómo funcionan estos símbolos depende en gran medida del entorno y el idioma.

+1

Esto es solo acerca de símbolos. Hay mucho más para depurar que los símbolos. –

9

Si estás en un sistema operativo Windows, un gran recurso para esto sería "Aplicaciones de depuración para Microsoft .NET y Microsoft Windows" de John Robbins:

(o incluso la edición anterior: "Debugging Applications")

El libro tiene un capítulo sobre cómo funciona un depurador que incluye código para un par de depuradores simples (pero que funcionan).

Como yo no estoy familiarizado con los detalles de la depuración de Unix/Linux, esto puede no ser aplicable en absoluto a otros sistemas operativos. Pero supongo que, como introducción a un tema muy complejo, los conceptos, si no los detalles y las API, deberían 'portar' a casi cualquier sistema operativo.

23

En Linux, la depuración de un proceso comienza con la llamada al sistema ptrace(2). This article tiene un excelente tutorial sobre cómo usar ptrace para implementar algunas construcciones simples de depuración.

+1

¿El '(2)' nos dice algo más (o menos) que "ptrace es una llamada al sistema"? – Lazer

+5

@eSKay, no realmente. El '(2)' es el número de sección manual. Consulte http://en.wikipedia.org/wiki/Man_page#Manual_sections para obtener una descripción de las secciones del manual. –

+2

@ AdamRosenfield Excepto por el hecho de que la sección 2 es específicamente "Llamadas al sistema". Entonces indirectamente, sí, nos dice que 'ptrace' es una llamada al sistema. –

3

Otra fuente valiosa para entender la depuración es el manual de la CPU Intel (Intel® 64 y IA-32 Architectures Software Developer's Manual). En el volumen 3A, capítulo 16, introdujo el soporte de hardware para la depuración, como excepciones especiales y registros de depuración de hardware. A continuación se muestra el capítulo:

Indicador T (trap), TSS - Genera una excepción de depuración (#DB) cuando se intenta para cambiar a una tarea con el indicador T establecido en su TSS.

No estoy seguro de si Windows o Linux usan esta bandera o no, pero es muy interesante leer ese capítulo.

Espero que esto ayude a alguien.

44

Como lo entiendo:

Para los puntos de interrupción de software en x86, el depurador reemplaza el primer byte de la instrucción con CC (int3). Esto se hace con WriteProcessMemory en Windows. Cuando la CPU llega a esa instrucción y ejecuta el int3, esto hace que la CPU genere una excepción de depuración. El sistema operativo recibe esta interrupción, se da cuenta de que el proceso se está depurando y notifica al proceso de depuración que se ha alcanzado el punto de interrupción.

Después de que se golpea el punto de interrupción y el proceso se detiene, el depurador busca en su lista de puntos de interrupción, y reemplaza el CC con el byte que estaba allí originalmente. El depurador establece TF, the Trap Flag en EFLAGS (modificando CONTEXT) y continúa el proceso. La bandera de trampa hace que la CPU genere automáticamente una excepción de un solo paso (INT 1) en la siguiente instrucción.

Cuando el proceso que se depura se detiene la próxima vez, el depurador reemplaza nuevamente el primer byte de la instrucción de punto de interrupción con CC, y el proceso continúa.

No estoy seguro de si así es exactamente como es implementado por todos los depuradores, pero he escrito un programa Win32 que logra depurarse utilizando este mecanismo. Completamente inútil, pero educativo.

Cuestiones relacionadas