===== Introducción ===== El Bochs es un emulador de la arquitectura IA-32. Esta aplicación //Open Source// puede ser ejecutada en varias plataformas, permitiendo simular de forma sencilla y controlada una PC completa, incluyendo los periféricos y el conjunto de integrados que la componen. También permite "conectar" los periféricos simulados, a ficheros o mecanísmos de IPC del host donde se ejecuta, para simular la interacción de la PC virtual con el mundo exterior. Una de las principales características que distinguen este emulador de otros como Virtual Box o VM Ware, es la funcionalidad de depuración, la cual permite un seguimiento completo del código que ejecuta la CPU así como también inspeccionar el estado de todos sus registros, visualizar el contenido de la memoria y analizar el estado de los periféricos. Esta aplicación se puede instalar tanto en Windows como en Linux, aunque las opciones de configuración varían de un sistema al otro, debido principalmente a la forma de interactuar con el resto del host de desarrollo ( el "mundo exterior" de la simulación ). Ambas se pueden descargar de la web oficial del proyecto, [[http://bochs.sourceforge.net/]] La versión de Windows incluye por defecto dos ejecutables, uno para el modo normal (llamado "bochs") y otro para el depurador (llamado "bochsdbg"). Las versiones de Linux que se instalan a través de los gestores de paquetes solo suelen incluir el ejecutable para el modo normal, debiendo el usuario descargar los fuentes y compilarlo con las opciones correspondientes, lo que generará un ejecutable también llamado "bochs" a secas, pero que si utilizará el modo de depuración. En la Cátedra solo se utilizará y brindará soporte, de la versión __//**homologada**//__ por la misma, para la instalación y configuración en un entorno Linux. La Cátedra provee una imágen de Linux ([[td3:instalacion_de_la_imagen_de_linux_de_la_catedra|Linux TDiii]]) que dispone de la aplicación instalada, pero no configurada. En los apartados subsiguientes se detalla el proceso de instalación y configuración, tanto para el depurador interno como para GDB. ===== Instalación ===== Ver también: [[https://www.alpertron.com.ar/videos/bochs.htm|Video de instalación de Bochs en Linux]]. A continuación se detallan los pasos necesarios (ante problemas recuerde leer las [[td3:bochs|FAQ]]) para la instalación de la aplicación tanto con la interfaz de depuración propia del Bochs, como con GDB (GNU DeBugger).\\ La versión homologada por la Cátedra y con la cual se analizarán y //**evaluarán**// los trabajos prácticos es la **__2.6.9__** (MM=2.mm=6.vv=9). - Descargar la versión homologada desde [[https://sourceforge.net/projects/bochs/files/bochs/2.6.9/bochs-2.6.9.tar.gz/download]] - Descomprimir el paquete de instalación en un directorio de trabajo temporario, mediante el comando:\\ tar -xzvf bochs-MM.mm.vv.tar.gz -C /su_directorio_temporal * -x: Extrae el contenido del fichero. * -z: Descomprime el contenido mediante gzip. * -v: Muestra en pantalla todas las salidas del comando (modo verbose). * -f: Especifica que fichero //tar// debe ser tomado como argumento. * -C: Indica la ruta a la carpeta donde se desea descomprimir el fichero.\\ Para mayores detalles man tar - Si la operación fue exitosa, se observará en **// /su_directorio_temporal/bochs-MM.mm.vv //** todos los fuentes de la aplicación, mediante\\ cd su_directorio_temporal/bochs-MM.mm.vv/ ls - Verificar que se disponen de todas las dependencias (librerías) necesarias para que la aplicación pueda ser instalada y funcionar correctamente.\\ sudo apt-get update sudo apt-get install nasm build-essential gtk-2.0 libgtk2.0-dev Dependiendo de la distribución de Linux, el GTK puede venir preinstalado o no. ==== Interfaz de depuración BOCHS ==== Para la configuración de la interfaz de depuración interna de Bochs se deben seguir los siguientes lineamientos: - El //script// **configure**, permite establecer las opciones de compilación con las cuales se creará la aplicación. Dicho script se debe ejecutar en el directorio donde se encuentra el código fuente, es decir que debe ejecutarse después de haber realizado el paso 3 de la sección anterior. Es posible visualizar todas las opciones brindadas mediante\\ ./configure --help | less , o bien ingresando a [[http://bochs.sourceforge.net/doc/docbook/user/compiling.html]].\\ Por defecto en la Cátedra se emplearán las siguientes opciones:\\ ./configure --enable-x86-64 --enable-smp --enable-usb --enable-usb-ohci --enable-debugger --enable-disasm --enable-x86-debugger --disable-docbook Verificar que no se visualicen errores al finalizar la ejecución del comando indicado. * **--enable-x86-64**: Habilita el soporte del conjunto de instrucciones x86-64 (64bit). * **--enable-smp**: Habilita el multiprocesamiento simétrico. * **--enable-usb**: Habilita el soporte para USB UHCI * **--enable-usb-ohci**: Habilita el soporte para USB OHCI * **--enable-debugger**: Habilita el depurador interno de Bochs. Para nuestros objetivos, esta es la herramienta más útil de la aplicación. * **--enable-disasm**: Habilita el desensamblado de un binario. * **--enable-x86-debugger**: Permite utilizar los registros de depuración de los procesadores Intel. * **--disable-docbook**: Deshabilita la generacion de documentación. Requiere dependencias que ocupan un espacio no menor y no es de gran utilidad - Luego ejecutaremos los comandos:\\ make sudo make install ==== Interfaz de depuración GDB (opcional) ==== Para disponer de la interfaz de depuración GDB, se deben repetir los pasos pasos detallados en [[bochs | Interfaz de depuracion BOCHS]], pero reconfigurando las siguientes opciones * La carpeta de instalación debe ser diferente al seleccionado previamente, por ejemplo bastaria con agregar el sufijo _gdb es decir _gdb. Esto es necesario ya que el binario de la aplicación generado en [[bochs | Interfaz de depuracion BOCHS]] es diferente al que se generará en esta instancia, al igual que las opciones de configuracion. * **--enable-gdb-stub**: Esta opción habilita GDB como interfaz de depuración, siendo __//mutuamente excluyente//__ con **--enable-debugger**, es decir que esta última debe ser __//eliminada//__. * **--enable-smp**: GDB no soporta depuración en un entorno de multiprocesamiento, por lo que esta opción se debe __//quitar//__. Antes de ejecutar el comando //make//, se debe verificar que los paquetes **//libxrandr-dev//** y **//gdb//** se encuentren disponibles, a tal fin basta ejecutar sudo apt-get install “nombre del paquete” Adicionalmente, se deberá cambiar la ruta de acceso de la opción --prefix, de manera que se instale sin sobrescribir la instalación previa de forma tal de disponer de ambas alternativas. Para ello solo basta con especificar --prefix=/var/tmp/bochs-MM.mm.vv-gdb ===== Configuración ===== La configuración de la aplicación puede ser llevada a cabo fácilmente mediante su interfaz de edición, para inicializarla solo basta con ejecutar **bochs** y seleccionar la opción //Edit options// y una vez finalizada la edición guardar la configuración mediante //Save options to// en **.bochsrc** ==== Depurador BOCHS ==== A continuación se detallan las opciones más relevantes para utilizar con el depurador interno del Bochs. * **Logfile options**: permite establecer los ficheros en los cuales se almacenarán los mensajes de información provistos por el depurador y la consola de control. Seleccionar la opción deseada e indicar el nombre del fichero en el cual se desea almacenar la información, por ejemplo //console.log// y //debugger.log// para la consola y el depurador respectivamente. * **CPU Options**: esta configuración es una de las más importantes ya que establece que tipo de CPU se simulará. En la Cátedra se utilizará la siguiente configuración: * //CPU configuration// **bx_generic** * //Emulated instructions per second (IPS)// **2500000** * Las opciones no especificadas deben disponer de su valor por defecto * **CPUID Options**: establece las caracterìsticas del CPU a simular * //Support for SSE instruction set// **sse4_2** * //Support for XSAVE instruction // **yes** * //Support for XSAVEOPT instruction // **yes** * //1G pages support in long mode // **yes** * //PCID support in long mode // **yes** * //FS/GS BASE acces instructions support // **yes** * //Supervisor Mode Execution Protection support // **yes** * //Supervisor Mode Access Protection support // **yes** * Las opciones no especificadas deben disponer de su valor por defecto * **Memory options**: establece la memoria a simular por el emulador y la que el //host// le asignará * //Standard Options->RAM size options->memory size// **512** * //Standard Options->RAM size options->host memory size// **512** * //Standard Options->ROM image options->file// **ruta a la imagen de bios** * //Standard Options->ROM image options->address// **0xf0000** * **Clock & CMOS options**: establece las opciones de configuración de la BIOS referentes al reloj * //Synchronisation method// **slowdown** * **Disk & Boot options**: permite especificar el dispositivo desde el cual se iniciará la PC simulada y que unidades de disco dispondrá * //First Floppy Drive->What type of floppy drive// **3.5" 1.44M** * //First Floppy Drive->Enter new filename// **floppy.img** * //First Floppy Drive->What type of floppy media// **1.44M** * //First Floppy Drive->Is media write protected// **no** * //First Floppy Drive->Is the device inserted...// **inserted** * //Boot Options->Boot drive #1// **floppy** * Existen algunas opciones de configuración que no se encuentran accesibles desde la interfaz de edición, para lo cual con algùn editor de texto se abrirá el fichero creado (.bochsrc), y se modificará el valor de la opciones, en especial * //magic_break: enabled=//**1** : Permite insertar //breakpoints// en el código fuente. Es importante destacar que esta metodologìa no debe ser utilizada para la depuración salvo excepciones, ya que para insertar //breakpoints// se debe emplear el comando del depurador, tal como se detallará en [[bochs | Breakpoints]]. * //display_library: x// : En esta lìnea para disponer de una interfaz de depuración gráfica, se debe agregar, options="gui_debug" ==== Depurador GDB ==== La configuración de Bochs para su utilización con GDB, solo debe ser aplicada si se generó el binario como se indica en [[bochs | Interfaz de depuración GDB]], adicionalmente debe seguir los pasos detallados en [[bochs | Depurador BOCHS]], con las siguientes modificaciones: * //Other options->GDB Stub Options->Enable GDB stub// **yes** * Las no especificadas deben disponer de su valor por defecto Adicionalmente al iniciar **DDD** (la GUI de GDB), se debe configurar la interfaz con la cual se conectará con Bochs, para ello bastará con ejecutar en la consola de **DDD** target remote localhost:1234 y esperar la respuesta Connected to 127.0.0.1 ===== Argumentos de la linea de comandos ===== Visualizar la ayuda disponible /opt/bochs-2.6.9-int/bin/bochs --help Cargar la configuración desde un fichero específico /opt/bochs-2.6.9-int/bin/bochs -f ===== Comandos del depurador interno ===== La lista completa de los comandos provistos por Bochs se encuentra en [[http://bochs.sourceforge.net/doc/docbook/user/internal-debugger.html]], o simplemente ejecutando //help// en la consola del depurador. Sin embargo a continuación se detallan los que son considerados más relevantes. ==== Breakpoints ==== Sin lugar a duda al momento de desarrollar cualquier aplicación resulta de suma utilidad, detener la ejecución de código en puntos conocidos, ya sea para inspeccionar a posteriori el contenido de ciertas variables o bien para analizar condiciones de error. A tal fin el depurador del Bochs, cuenta con la familia de comandos //break// o bien su abreviatura //b// vb seg:off lb linearaddress b physicaladdress Como se verá durante el desarrollo de los problemas, el siguiente comando detiene la ejecución de código en la dirección lógica asociada al segundo descriptor (//0x10//) de la GDT en la instrucción ubicada en el desplazamiento //0x89a//, a partir de la base del descriptor mencionado. vb 10:89a Si la base del descriptor se inicializa en //0x0//, el siguiente comando detendrá la ejecución en el mismo punto que el anterior, es decir en la dirección lìneal //0x89a// lb 0x89a Por otro lado si se trabaja en un esquema de paginación en el cual las direcciones lógicas coincidan con las físicas (//identity mapping//), el siguiente comando generará los mismos efectos que los descriptos anteriormente. b 0x89a ==== Control de ejecución ==== En conjunto con los //breakpoints// una de las funcionalidades más potentes de un depurador es la capacidad de controlar la ejecución de un programa. Como es bien sabido un depurador permite ejecutar instrucciones paso a paso s continuar con la ejecución hasta el final o el próximo //breakpoint// c o bien continuar con la ejecución de la instrucción inmediatamente posterior a una rutina, sin la necesidad de recorrerla paso a paso p ==== Inspección de las tablas de descriptores ==== Uno de los comandos más útiles y de los primeros que se utilizarán al momento de realizar la guía de trabajos prácticos es info gdt n info idt n Estos comandos permiten visualizar el contenido del descriptor //n// de la Tabla Global de Descriptores (GDT) y la Tabla de Descriptores de Interrupción (IDT), respectivamente. En caso de requerir el análisis de las tabla completa, solo basta con omitir el parámetro. Es muy ilustrativo comparar los descriptores utilizados en modo IA-32e tanto para 32b como para 64b. ==== Inspección de memoria ==== El contenido de la memoria puede ser inspeccionado mediante el comando 'x' (para ver la memoria lineal), o el comando 'xp' (para ver la memoria física), de acuerdo a la siguiente regla: x / donde **** es la cantidad de posiciones consecutivas que quieren ver. **** es el formato número en el que lo quieren ver (x para hexadecimal, d para decimal). **** es el tamaño de la posición (b para byte, h para 16 bits y w para 32 bits). Como se puede apreciar es posible inspeccionar el contenido de la memoria, ya sea con de las direcciones lineales o de las direcciones físicas. Este comando es sumamente útil en el desarrollo de la guía de trabajos prácticos para todo aquello referido a paginación, asi como también para inspeccionar el estado de variables, o el contenido de tablas y/o cadenas. Asi, por ejemplo, el siguiente comando del depurador mostrará los 10 bytes de memoria a partir de la dirección lineal 0x1000, en formato hexadecimal. x /10xb 0x1000 De forma similar, el siguiente comando mostrará los 10 dwords de memoria a partir de la dirección lineal 0x1000, en formato hexadecimal. x /10xw 0x1000 Si en cambio quisieramos ver los 10 bytes de memoria a partir de la dirección lineal 0x1000, pero en formato decimal, deberíamos ejecutar: x /10db 0x1000 ==== Traducción de las direcciones lineales paginadas a físicas ==== Uno de los principales escollos que el desarrollador se encuentra al momento de resolver los ejercicios relacionados con paginación, es verificar que el mapa de memoria implementado en código coincida con el requerido. Para tal fin, existen los comandos page info tab El primer comando permite no solo realizar la traducción de la dirección líneal paginada a su correspondiente dirección física, sino también permite visualizar la inicialización de los registros y entradas de paginación asociadas. El segundo caso permite visualizar las traducciones de las direcciones lineales a físicas, para **toda** la memoria RAM del sistema, es decir se observarán las traducciones que se inicializaron correctamente y las que tienen un contenido erroneo. A continuación se muestran algunos ejemplos, el primero de los cuales no utiliza la unidad de paginación, mientras que en el segundo la misma se encuentra activa para el modo IA32e 64b. En todos los casos la dirección lineal coincide con la física (//identity mapping//) page 0 linear page 0x0000000000000000 maps to physical page 0x0000000000000000 page 0x8000 PML4: 0x0000000000011021 ps A pcd pwt S R P PDPE: 0x0000000000012021 ps A pcd pwt S R P PDE: 0x00000000000000e7 PS g pat D A pcd pwt U W P linear page 0x0000000000008000 maps to physical page 0x0000000000008000 info tab 0x00000000-0x000fffff -> 0x0000000000000000-0x00000000000fffff (Primer megabyte correctamente inicializado) 0x54a20000-0x54a20fff -> 0x0000003df000e000-0x0000003df000efff (Traducciones sin ... inicilizar 0xd62e7000-0xd62e7fff -> 0x000000000298e000-0x000000000298efff para 48MB de RAM) ==== Inspección de la pila ==== En el caso de querer analizar el //stack//, se puede optar por dos alternativas. * Utilizar el mismo mecanismo empleado para inspeccionar memoria, utilizando la dirección lineal que se conforma a partir de la dirección lógica SS:ESP. * Mediante el comando print-stack [num words] Al ejecutar el mismo se podrá ver el contenido de los primeros multiplos de 16 bit especificados como argumento, mediante //num words//. Recordar que si se desea inspeccionar el contenido que se guardó en primera instancia, se debe leer en forma completa la pila, ya que el comando mencionado realiza una lectura tipo //TOP-DOWN//, por lo cual basta omitir el argumento. Este comando es de mucha utilidad a la hora de depurar excepciones, ya que permite de forma rápida ver el par CS:EIP que causó la excepción, y el //ErrorCode// de la misma si lo hubiere. ==== Inspección de dispositivos ==== En ciertos casos puede resultar de utilidad observar el estado de un dispositivo especìfico, sobre todo el PIC y el PIT en nuestro entorno de trabajo. A tal fin se dispone del comando\\ info device "dispositivo" Por ejemplo para el caso del PIT\\ info device "pit" 82C54 PIT GATE #2 = 1 Speaker = 0 counter #0; freq=18,206, OUT=1 counter #1; freq=18,206, OUT=1 counter #2; freq=18,206, OUT=1 Supported options: info device 'pit' 'counter=N' - show status of counter N Se puede observar que además de brindarnos la información completa de la configuración y el estado de cada contador, se indica que es posible seleccionar un elemento en forma individual para conocer su estado, en forma detallada\\ info device "pit" "counter=1" 82C54 PIT GATE #2 = 1 Speaker = 0 counter #0; freq=18,206 count: 40456 count_binary: 0x9e08 counter GAT: 1 counter OUT: 1 next_change_time:0 Es importante destacar que tanto los dispositivos como las opciones debe especificarse como argumentos tipo cadena, es decir entre comillas. --- //[[cnigri@frba.utn.edu.ar|ChristiaN]] 2019/07/29 22:33// ===== FAQ ===== * **¡Al ejecutar el comando //apt-get build-dep bochs// se presenta el error //Debe poner algunos URIs 'fuente' en su sources.list//!** Como parte de su funcionamiento, APT utiliza un archivo que enlista las "fuentes" en donde se encuentran los paquetes. Este archivo en Debian es **/etc/apt/sources.list** y bastarà con agregar las siguientes lìneas\\ deb http://http.us.debian.org/debian stable main contrib non-free deb http://security.debian.org stable/updates main contrib non-free Para mayores detalles refirise a [[http://www.debian.org/doc/manuals/apt-howto/ch-basico.es.html]] En caso de utilizar Ubuntu bastara con habilitar "sources" mediante la interfaz //Software & Updates// * **¡El comando //make install// finaliza con un mensaje que contiene un texto similar a //undefined reference to symbol 'pthread_create@@GLIBC_2.2.5//!** Agregar la siguiente opción LDFLAGS='-pthread' al momento de realizar la configuración. * **¡El comando //make install// finaliza con un mensaje similar a //mkdir: no se puede crear el directorio «/opt/bochs-...//!** Como ///opt/// solo puede ser modificado por root, se debe ejecutar //sudo make install// * **¡Instale la aplicación en /tmp/ y al reiniciar la PC se borró!** Efectivamente es el funcionamiento esperado, ya que /tmp/ es un directorio de ficheros no persistentes. Por este motivo se debe instalar en /var/tmp/. * **¿Puedo instalar el Bochs en otra ubicación?** __**NO**__. La ubicación indicada permite que todos los scripts sean compatibles facilitando el trabajo de desarrollo y evaluación.