# Depurador

Un depurador (en inglés: debugger) es un programa que se utiliza para detectar e identificar los errores en un software (el programa "objetivo") y, por lo tanto, los desarrolladores pueden encontrar los fallos en el programa de forma más fácil, facilitando el proceso de corrección. El código a ser examinado puede alternativamente estar corriendo en un simulador de conjunto de instrucciones (ISS), una técnica que permite gran potencia en su capacidad de detenerse cuando son encontradas condiciones específicas pero será típicamente algo más lento que ejecutando el código directamente en el apropiado (o el mismo) procesador. Algunos depuradores ofrecen dos modos de operación, la simulación parcial o completa, para limitar este impacto.
Si es un depurador de nivel de fuente o depurador simbólico, comúnmente ahora visto en entornos de desarrollo integrados, cuando el programa "se estrella" o alcanza una condición predefinida, la depuración típicamente muestra la posición en el código original. Si es un depurador de bajo nivel o un depurador de lenguaje de máquina, muestra la línea en el fuente desensamblado (a menos que también tenga acceso en línea al código fuente original y pueda exhibir la sección apropiada del código del ensamblador o del compilador). Un "estrellamiento" sucede cuando el programa no puede continuar normalmente debido a un error de programación. Por ejemplo, el programa pudo haber intentado usar una instrucción no disponible en la versión actual del CPU o haber intentado tener acceso a memoria protegida o no disponible.
Típicamente, los depuradores también ofrecen funciones más sofisticadas tales como correr un programa paso a paso (un paso o animación del programa), parar el programa (breaking), es decir, pausar el programa para examinar el estado actual en cierto evento o instrucción especificada por medio de un breakpoint, y el seguimiento de valores de algunas variables. Algunos depuradores tienen la capacidad de modificar el estado del programa mientras que está corriendo, en vez de simplemente observarlo. También es posible continuar la ejecución en una posición diferente en el programa bypaseando un estrellamiento o error lógico.
La importancia de un buen depurador no puede ser exagerada. De hecho, la existencia y la calidad de tal herramienta para un lenguaje y una plataforma dadas a menudo puede ser el factor de decisión en su uso, incluso si otro lenguaje/plataforma es más adecuado para la tarea. La ausencia de un depurador, una vez estando acostumbrado a usar uno, se ha dicho que "hace que usted se sienta como un hombre ciego en un cuarto oscuro buscando un gato negro que no está allí". Sin embargo, el software puede (y a menudo) se comporta diferentemente corriendo bajo un depurador que normalmente, debido a los cambios inevitables que la presencia de un depurador hará a la temporización interna de un programa de software. Como resultado, incluso con una buena herramienta de depuración, es a menudo muy difícil rastrear problemas de tiempo de corrida en complejos sistemas distribuidos con múltiples hilos.
La misma funcionalidad que hace a un depurador útil para eliminar errores permite ser usado como herramienta de craqueo de software para evadir la protección anticopia, la gestión digital de derechos, y otras características de protección de software. A menudo también lo hace útil como herramienta general de verificación de pruebas, cobertura de fallas, o analizador de desempeño, especialmente si son mostradas las longitudes de trayectoria de instrucción.
La mayoría de los motores de depuración actuales, tales como gdb y dbx proporcionan interfaces basadas en línea de comandos. Los frontales de depuración son extensiones populares a los motores de depuración, que proporcionan integración al IDE, animación del programa, y características de visualización. Algunos depuradores de los primeros mainframes tales como el Oliver y el SIMON proporcionaron esta misma funcionalidad para el IBM System/360 y posteriores sistemas operativos, hasta los años 1970.

## Dependencia del lenguaje

Algunos depuradores operan en un simple lenguaje específico mientras que otros pueden manejar múltiples lenguajes transparentemente. Por ejemplo si el programa objetivo principal es escrito en COBOL, pero llama a subrutinas en assembler y también subrutinas en PL/1, el depurador puede cambiar modos dinámicamente para acomodar los cambios en el lenguaje a medida que ocurren.

## Protección de memoria

Algunos depuradores también incorporan protección de memoria para evitar violaciones del almacenamiento tales como desbordamiento de búfer. Esto puede ser extremadamente importante en los ambientes de procesamiento de transacciones donde la memoria es dinámicamente asignada desde "pools" de memoria en una base de tarea por tarea.

## Soporte de hardware para la depuración

La mayoría de los microprocesadores modernos tienen al menos una de estas características en su diseño de CPU para hacer la depuración más fácil:
* Soporte en hardware para ejecutar un programa paso a paso, tal como el trap flag.
* Un conjunto de instrucciones conformado con los requerimientos de virtualización de Popek y Goldberg, hace más fácil escribir el software depuración que corre en el mismo CPU que el software que está siendo depurado; tal CPU puede ejecutar los bucles internos del programa bajo prueba a velocidad completa, y todavía permanecer bajo control del depurador.
* In-system programming (ISP) (programación en sistema) permite a un depurador de hardware externo reprogramar un sistema bajo prueba, por ejemplo, adición o eliminación de instrucciones de puntos de ruptura (breakpoints). Muchos sistemas con tal soporte de ISP también tienen otro soporte de hardware de depuración.
* Soporte de hardware para breakpoints de código y datos, tales como comparadores de direcciones y comparadores de valores de datos, o con considerablemente más trabajo implicado, hardware de fallo de página.
* El acceso de JTAG a las interfaces de depuración de hardware tales como en procesadores de la arquitectura ARM o usando el conjunto de comandos Nexus. Los procesadores usados en sistemas empotrados típicamente tienen extenso soporte de depuración JTAG.
* Los microcontroladores con tan poco como seis pines necesitan usar sustitutos de bajo conteo de pines para JTAG, tal como BDM, Spy-Bi-Wire, o DebugWire en el Atmel AVR. DebugWire, por ejemplo, usa señalización bidireccional en el pin del RESET.

## Uso

El depurador lanza el programa a depurar. Este se ejecuta normalmente hasta que el depurador detiene su ejecución, permitiendo al usuario examinar la situación.
El depurador permite detener el programa en:
* Un punto determinado mediante un punto de ruptura.
* Un punto determinado bajo ciertas condiciones mediante un punto de ruptura condicional.
* Un momento determinado cuando se cumplan ciertas condiciones.
* Un momento determinado a petición del usuario.
Durante esa interrupción, el usuario puede:
* Examinar y modificar la memoria y las variables del programa.
* Examinar el contenido de los registros del procesador.
* Examinar la pila de llamadas que han desembocado en la situación actual.
* Cambiar el punto de ejecución, de manera que el programa continúe su ejecución en un punto diferente al punto en el que fue detenido.
* Ejecutar instrucción a instrucción.
* Ejecutar partes determinadas del código, como el interior de una función, o el resto de código antes de salir de una función.
El depurador depende de la arquitectura y sistema en el que se ejecute, por lo que sus funcionalidades cambian de un sistema a otro. Aquí se han mostrado las más comunes.

## Información de depuración

Para poder aprovechar todas las posibilidades de depuración es necesario que, al compilar el programa a depurar, se indique al compilador que debe incluir instrucciones e información extra para la depuración del código. Dicha información extra consiste básicamente en la correspondencia entre las instrucciones del código ejecutable y las instrucciones del código fuente que las originan, así como información sobre nombres de variables y funciones.
Aun si no se incluye esta información de depuración, sigue siendo posible monitorizar la ejecución del programa. Sin embargo, resultará más difícil y compleja debido a esa falta de información del contexto en el que se ejecuta el programa.

## Otros usos

Un depurador también puede usarse para realizar ingeniería inversa o evitar protecciones de copia. Mediante el uso del depurador se puede conocer el funcionamiento interno del programa examinado, ayudando al proceso de ingeniería inversa o permitiendo desarrollar técnicas para evadir las restricciones impuestas por el programa.

## Efectos secundarios

Es importante notar que un programa que está siendo depurado puede presentar un comportamiento diferente a si se ejecuta en solitario debido a que el depurador cambia ligeramente los tiempos internos del programa. Estos cambios en los tiempos de ejecución afectan especialmente a complejos sistemas distribuidos.

## Ejemplos de depuradores

* Visual DuxDebugger — Debugger Disassembler for Windows 64-bit
* GNU Debugger (gdb)
* SoftICE
* OllyDbg
* Trw2000
* Ida Pro
* Winpdb
* Cheat Engine