Apunte sobre Bochs Programación de Sistemas Operativos 1 er Cuatrimestre 2011 Índice 1. Introducción 1 1.1. bochs - VM con Debugger.................................. 2 2. Bochs 2 2.1. Instalación.......................................... 2 2.2. Menu de bochs........................................ 3 2.3. Archivo de configuración................................... 3 3. Arranque de la máquina virtual 4 4. Debug en bochs 4 4.1. Referencia breve....................................... 5 4.1.1. Next y Step...................................... 5 4.1.2. Registros de uso general............................... 5 4.1.3. Memory Dump.................................... 6 4.1.4. Memory Disassemble................................. 6 4.1.5. Breakpoints...................................... 6 4.1.6. Watchs........................................ 7 4.1.7. Infos.......................................... 7 4.1.8. Registros de Segmento................................ 7 4.1.9. Registros de Control................................. 7 1. Introducción El procesador posee intrucciones de lenguaje ensamblador y tablas internas que sólo se pueden ejecutar en nivel privilegio elevado o anillo 0. No es posible acceder a estos mecanismos desde un proceso de usuario común y corriente, dado que ejecuta en un nivel de privilegio bajo. Entonces, es necesario ejecutar código en el sistema operativo, para realizar cosas como: Utilizar instrucciones de nivel privilegiado Acceder a los mecanismos de manejo de memoria Cambiar los modos del procesador Controlar interrupciones Para ejecutar nuestro sistema operativo vamos a usar una Virtual Machine. 1
1.1. bochs - VM con Debugger Un debugger como gdb es un proceso más del sistema operativo. Por lo tanto, no puede monitorear el funcionamiento interno del sistema operativo, instrucción por instrucción. Entonces, es necesario utilizar un debugger dentro del sistema operativo, pero sin ayuda de éste, dado que será el objeto de análisis. Para esto, es necesario un debugger a más bajo nivel: un debugger en la Virtual Machine. 2. Bochs 2.1. Instalación Bochs + Debugger Bochs es un simulador de una computadora entera, por lo que nos permite ejecutar instrucción por instrucción el procesador, incluyendo las instrucciones ejecutadas por el sistema operativo. Pero su versión oficial no está compilada con esta posibilidad. Para usarla, hay que compilarlo a mano. Manos a la obra! 1. bajar de: http://sourceforge.net/projects/bochs/files/bochs/2.4.6/ el archivo bochs-2.4.6.tar.gz 2. descomprimir: tar -xvzf bochs-2.4.6.tar.gz 3. en el directorio descomprimido hacer:./configure --enable-debugger --enable-disasm --disable-docbook --prefix=/home/<usuario> /bochs-2.4.6/ make make install En caso de instalar el bochs en la home del usuario (requiere poner la opción --prefix mencionada arriba), podemos usar bochs desde cualquier path incluyéndolo en la lista de path del sistema. Hacemos esto, agregando en el archivo ~/.bashrc la linea que incluye tal path. Agregar en el archivo /home/< usuario >/.bashrc export PATH+=":/home/< usuario >/bochs-2.4.6/bin/" Esto cargará el path correcto la próxima vez que iniciemos una consola. Para que carge los cambios en nuestra consola actual, ejecutamos: source.bashrc 2
Como alternativa a la instalación en la home del usuario se puede instalar en el sistema. Esta opción es más simple y recomendada, pero para esto es necesario contar con permisos de administrador de la máquina en cuestión. En este caso, los pasos del tercer punto no incluyen la opción --prefix, quedando así:./configure --enable-debugger --enable-disasm --disable-docbook make sudo make install Esto instala el programa en la ruta por omisión /usr/local/bin. Es recomendable para este caso desinstalar cualquier versión de bochs que fuera previamente instalada como parte de la distribución de linux utilizada. 2.2. Menu de bochs Al ejecutar el bochs vemos una pantalla como la siguiente: ------------------------------ Bochs Configuration: Main Menu ------------------------------ This is the Bochs Configuration Interface, where you can describe the machine that you want to simulate. Bochs has already searched for a configuration file (typically called bochsrc.txt) and loaded it if it could be found. When you are satisfied with the configuration, go ahead and start the simulation. You can also start bochs with the -q option to skip these menus. 1. Restore factory default configuration 2. Read options from... 3. Edit options 4. Save options to... 5. Restore the Bochs state from... 6. Begin simulation 7. Quit now Please choose one: [6] Para saltear esta pantalla se puede ejecutar el bochs utilizando la opción -q: bochs -q 2.3. Archivo de configuración La configuración de las opciones de bochs se realiza a través de un archivo de configuración llamado bochsrc. En este archivo se especifica la máquina a emular, indicando qué discos tiene, diskettes, memoria, procesador, puerto serie, etc. A continuación hay un ejemplo de bochsrc: config_interface: textconfig romimage: file=$bxshare/bios-bochs-latest vgaromimage: file=$bxshare/vgabios-lgpl-latest vga: extension=vbe cpu: count=1, ips=50000000, reset_on_triple_fault=1, ignore_bad_msrs=1, msrs="msrs.def" megs: 32 3
floppya: image=floppy.img, status=inserted floppy_bootsig_check: disabled=0 boot: floppy log: bochsout.txt magic_break: enabled=1 debug_symbols: file="kernel.sym" parport1: enabled=1, file="parport.out" mouse: enabled=0 panic: action=ask error: action=report info: action=report debug: action=ignore debugger_log: - vga_update_interval: 50000 keyboard_serial_delay: 250 keyboard_paste_delay: 100000 private_colormap: enabled=0 keyboard_mapping: enabled=0, map= i440fxsupport: enabled=1 Junto con bochs pueden encontrar un archivo bochsrc de ejemplo con comentarios detallando el funcionamiento de cada opción. Si el programa se encuentra instalado en /usr/local/bin/ entonces este archivo de ejemplo se puede encontrar en /usr/local/share/doc/bochs/bochsrc-sample.txt. Se puede descargar una imagen de linux de ejemplo o diskettes de http://bochs.sourceforge. net/diskimages.html. 3. Arranque de la máquina virtual Cuando una computadora inicia sólo existe el BIOS (Basic Input/Output system). En este momento es necesario realizar ciertas verificaciones básicas del sistema, e inicializar los dispositivos físicos, como la pantalla de video, el teclado, etc. Esto lo realiza el BIOS. El proceso de booteo comienza ejecutando el código del BIOS, ubicado en la posición 0xFFFF0, en modo real. El BIOS tiene el código en ROM, que realiza la inicialización (por ejemplo, la placa de video) y una verificación de la máquina (POST, Power-On Self Test). Luego busca algún dispositivo de booteo: Disco rígido, Floppy, USB, etc... Normalmente las opciones de configuración que el BIOS permite realizar se guardan en una memoria separada del código del BIOS, llamada NVRAM. De estas opciones el BIOS elige el orden en que buscará los dispositivos de booteo. Una vez localizado el dispositivo de arranque, carga el primer sector de 512 bytes (excepto en el caso de CDROM, cuyo tamaño es 2048) en la posición de memoria 0x07C00 y salta a esa dirección. Para determinar si un dispositivo tiene una sector de arranque, el primer sector debe estar firmado, es decir, debe tener en los últimos dos bytes el valor 0x55AA. Ahora este sector de arranque es el encargado de cargar un kernel e iniciar el sistema operativo dándole el control a este kernel. 4. Debug en bochs Cuando el bochs inicia con el modo debug habilitado, arranca con el procesador detenido justo después de cargar el BIOS, pero antes de ejecutarlo, y en la dirección 0xFFFF0. Para ver el código del bootloader que fue cargado en 0x07C00 debemos esperar a que lo cargue y frenar antes de que comience a ejecutarlo. A continuación vemos un ejemplo de uso del debugger mostrando esto. 4
1. Creamos un breakpoint en la posición de memoria física donde comenzará a cargar el bootloader <bochs:1>break 0x07C00 2. Leemos la posición de memoria donde debería estar la firma del bootloader una vez que carga en memoria principal <bochs:2>x/1x 0x07C00+510 [bochs]: 0x00007dfe <bogus+ 0>: 0x00000000 3. Continuamos la ejecución, hasta que llegamos al breakpoint <bochs:3>c (0) Breakpoint 1, 0x00007c00 in?? () Next at t=49462126 (0) [0x00007c00] 0000:7c00 (unk. ctxt): cli ; fa 4. Nuevamente, podemos leer y notar que el BIOS cargo los 512bytes pertenecientes al bootloader, primer sector de la unidad <bochs:4>x/1x 0x07C00+510 [bochs]: 0x00007dfe <bogus+ 0>: 0x0000aa55 4.1. Referencia breve En esta sección incluimos una referencia de los comandos que se le puede indicar al debugger del bochs. 4.1.1. Next y Step s step stepi [count] - ejecuta [count] instrucciones n next p - ejecuta instrucciones sin entrar a las subrutinas c cont continue - continua la ejecución q quit exit - sale del debugger y del emulador Ctrl-C Detiene la ejecución y retorna al promt 4.1.2. Registros de uso general r reg regs registers - Lista los registros del CPU y sus contenidos <bochs:12> registers eax: 0x00000000 0 ecx: 0x00000000 0 edx: 0x00000543 1347 ebx: 0x00000000 0 esp: 0x00000000 0 ebp: 0x00000000 0 esi: 0x00000000 0 edi: 0x00000000 0 eip: 0x0000e05d eflags 0x00000046 id vip vif ac vm rf nt IOPL=0 of df if tf sf ZF af PF cf 5
4.1.3. Memory Dump x /nuf [addr] - Muestra el contenido de la dirección [addr] xp /nuf [addr] - Muestra el contenido de la dirección fisica [addr] nuf es número que indica cuantos valores se mostrarán, seguido de uno o más de los indicadores de formato. x : hex d : decimal u : sin signo o : octal t : binario c : char s : ascii i : instrucción select the size: b : byte h : word = half-word w : dobleword = word 4.1.4. Memory Disassemble u disasm disassemble [count] [start] [end] - desensambla intrucciones desde la dirección lineal [start] hasta [end] exclusive. u disasm disassemble switch-mode - Selecciona la sintaxis Intel o AT&T de asembler u disasm disassemble size = n - Setea el tamao del segmento a desensamblar 4.1.5. Breakpoints p pb break pbreak [addr] - Crea un breakpoint en la dirección física [addr] vb vbreak [seg:offset] - Crea un breakpoint en la dirección virtual [addr] lb lbreak [addr] - Crea un breakpoint en la dirección lineal [addr] d del delete [n] - Borra el breakpoint número [n] bpe [n] - Activa el breakpoint número [n] bpd [n] - Desactiva el breakpoint número [n] 4.1.6. Watchs watch - Muestra el estado actual de los watchs watch stop - Detiene la simulación cuando un watch es encontrado watch continue - No detiene la simulación si un wath es encontrado watch r read [addr] - Agrega un watch de lectura en la dirección física [addr] watch w write [addr] - Agrega un watch de escritura en la dirección física [addr] 6
4.1.7. Infos info break - Muestra los Breakpoint creados info eflags - Muestra el registro EEFLAGS info idt - Muestra el descriptor de interrupciones (idt) info ivt - Muestra la tabla de vectores de interrupción info gdt - Muestra la tabla global de descriptores (gdt) info tss - Muestra el segmento de estado de tarea actual (tss) info tab - Muestra la tabla de paginas 4.1.8. Registros de Segmento sreg - Muestra los registros de segmento <bochs:5> sreg cs:s=0xf000, dh=0xff0093ff, dl=0x0000ffff, valid=7 ds:s=0x0000, dh=0x00009300, dl=0x0000ffff, valid=7 ss:s=0x0000, dh=0x00009300, dl=0x0000ffff, valid=7 es:s=0x0000, dh=0x00009300, dl=0x0000ffff, valid=7 fs:s=0x0000, dh=0x00009300, dl=0x0000ffff, valid=7 gs:s=0x0000, dh=0x00009300, dl=0x0000ffff, valid=7 ldtr:s=0x0000, dh=0x00008200, dl=0x0000ffff, valid=1 tr:s=0x0000, dh=0x00008b00, dl=0x0000ffff, valid=1 gdtr:base=0x00000000, limit=0xffff idtr:base=0x00000000, limit=0xffff 4.1.9. Registros de Control creg - Muestra los registros de control <bochs:10> creg CR0=0x60000010: pg CD NW ac wp ne ET ts em mp pe CR2=page fault laddr=0x00000000 CR3=0x00000000 PCD=page-level cache disable=0 PWT=page-level writes transparent=0 CR4=0x00000000: osxsave smx vmx osxmmexcpt osfxsr pce pge mce pae pse de tsd pvi vme 7