debugging - sirve - ¿Cómo funciona un depurador?
que es un debug y para que sirve (6)
Como yo lo entiendo:
Para los puntos de interrupción del 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
, la bandera de trampa en EFLAGS
(modificando el 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 lo implementan todos los depuradores, pero he escrito un programa Win32 que logra depurarse usando este mecanismo. Completamente inútil, pero educativo.
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?
En Linux, la depuración de un proceso comienza con la ptrace(2) al sistema ptrace(2) . Este artículo tiene un excelente tutorial sobre cómo usar ptrace
para implementar algunas construcciones simples de depuración.
Los detalles de cómo funciona un depurador dependerán de lo que está depurando y de 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 a qué proceso asociarse, 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 de forma similar a cualquier UI, pero en lugar de eventos provenientes del sistema de ventanas, el sistema operativo generará eventos en función de lo que ocurra en el proceso que se depura, por ejemplo, una excepción. Ver WaitForDebugEvent .
El depurador puede 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 funciones de depuración para Windows.
El depurador puede usar información de archivos de símbolos para traducir de direcciones a nombres de variables y ubicaciones 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 SDK de acceso a la interfaz de depuración .
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 la máquina virtual proporciona la API de depuración en lugar del sistema operativo subyacente.
Otra fuente valiosa para comprender la depuración es el manual de 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. Lo siguiente es de ese capítulo:
Indicador T (trap), TSS: genera una excepción de depuración (#DB) cuando se intenta 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.
Según tengo entendido, cuando compila una aplicación o un archivo DLL, lo que compila contiene símbolos que representan las funciones y las variables.
Cuando tiene una compilación de depuración, estos símbolos son mucho más detallados que cuando se trata de una compilación de lanzamiento, lo que permite que el depurador le brinde 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.
Si tiene un sistema operativo Windows, un buen recurso para esto sería "Depurar aplicaciones para Microsoft .NET y Microsoft Windows" por John Robbins:
(o incluso la edición anterior: "Aplicaciones de depuración" )
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 no estoy familiarizado con los detalles de la depuración de Unix / Linux, es posible que esto no se aplique 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.