From 77eb93ce4eaf9667e1261fa7be0a9e9f8cc4d949 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Tue, 17 Dec 2019 19:47:47 -0700 Subject: Rename x86 dir to arch_x86 --- Makefile | 4 +- arch_x86/gdbstub_int.nasm | 110 +++++++++++++++ arch_x86/gdbstub_sys.c | 350 ++++++++++++++++++++++++++++++++++++++++++++++ arch_x86/gdbstub_sys.h | 138 ++++++++++++++++++ x86/gdbstub_int.nasm | 110 --------------- x86/gdbstub_sys.c | 350 ---------------------------------------------- x86/gdbstub_sys.h | 138 ------------------ 7 files changed, 600 insertions(+), 600 deletions(-) create mode 100644 arch_x86/gdbstub_int.nasm create mode 100644 arch_x86/gdbstub_sys.c create mode 100644 arch_x86/gdbstub_sys.h delete mode 100644 x86/gdbstub_int.nasm delete mode 100644 x86/gdbstub_sys.c delete mode 100644 x86/gdbstub_sys.h diff --git a/Makefile b/Makefile index c447411..e956044 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ # SOFTWARE. # -ARCH := x86 +ARCH := arch_x86 # Include a simple demo that can be debugged INCLUDE_DEMO = 1 @@ -38,7 +38,7 @@ BASE_ADDRESS = 0x500000 OBJECTS = gdbstub_rsp.o \ $(ARCH)/gdbstub_sys.o -ifeq ($(ARCH),x86) +ifeq ($(ARCH),arch_x86) CFLAGS += -m32 LDFLAGS += -m elf_i386 OBJECTS += $(ARCH)/gdbstub_int.o diff --git a/arch_x86/gdbstub_int.nasm b/arch_x86/gdbstub_int.nasm new file mode 100644 index 0000000..2495971 --- /dev/null +++ b/arch_x86/gdbstub_int.nasm @@ -0,0 +1,110 @@ +; +; Copyright (c) 2016-2019 Matt Borgerson +; +; Permission is hereby granted, free of charge, to any person obtaining a copy +; of this software and associated documentation files (the "Software"), to deal +; in the Software without restriction, including without limitation the rights +; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +; copies of the Software, and to permit persons to whom the Software is +; furnished to do so, subject to the following conditions: +; +; The above copyright notice and this permission notice shall be included in +; all copies or substantial portions of the Software. +; +; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +; SOFTWARE. +; + +bits 32 + +%define NUM_HANDLERS 32 + +section .data +global dbg_int_handlers + +; Generate table of handlers +dbg_int_handlers: +%macro handler_addr 1 + dd dbg_int_handler_%1 +%endmacro +%assign i 0 +%rep NUM_HANDLERS + handler_addr i + %assign i i+1 +%endrep + +section .text +extern dbg_int_handler + +%macro int 1 +dbg_int_handler_%1: + push 0 ; Dummy Error code + push %1 ; Interrupt Vector + jmp dbg_int_handler_common +%endmacro + +%macro inte 1 +dbg_int_handler_%1: + ; Error code already on stack + push %1 ; Interrupt Vector + jmp dbg_int_handler_common +%endmacro + +; Generate Interrupt Handlers +%assign i 0 +%rep NUM_HANDLERS + %if (i == 8) || ((i >= 10) && (i <= 14)) || (i == 17) + inte i + %else + int i + %endif +%assign i i+1 +%endrep + +; Common Interrupt Handler +dbg_int_handler_common: + pushad + push ds + push es + push fs + push gs + push ss + mov ebp, esp + + ; Stack: + ; - EFLAGS + ; - CS + ; - EIP + ; - ERROR CODE + ; - VECTOR + ; - EAX + ; - ECX + ; - EDX + ; - EBX + ; - ESP + ; - EBP + ; - ESI + ; - EDI + ; - DS + ; - ES + ; - FS + ; - GS + ; - SS + + push ebp + call dbg_int_handler + + mov esp, ebp + pop ss + pop gs + pop fs + pop es + pop ds + popad + add esp, 8 ; Pop error & vector + iret diff --git a/arch_x86/gdbstub_sys.c b/arch_x86/gdbstub_sys.c new file mode 100644 index 0000000..a73bc52 --- /dev/null +++ b/arch_x86/gdbstub_sys.c @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2016-2019 Matt Borgerson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "gdbstub.h" + +#ifdef __STRICT_ANSI__ +#define asm __asm__ +#endif + +#define SERIAL_COM1 0x3f8 +#define SERIAL_COM2 0x2f8 +#define SERIAL_PORT SERIAL_COM1 + +#define NUM_IDT_ENTRIES 32 + +/***************************************************************************** + * BSS Data + ****************************************************************************/ + +static struct dbg_idt_gate dbg_idt_gates[NUM_IDT_ENTRIES]; +static struct dbg_state dbg_state; + +/***************************************************************************** + * Misc. Functions + ****************************************************************************/ + +void *dbg_sys_memset(void *ptr, int data, size_t len) +{ + char *p = ptr; + + while (len--) { + *p++ = (char)data; + } + + return ptr; +} + +/* + * Get current code segment (CS register). + */ +uint32_t dbg_get_cs(void) +{ + uint32_t cs; + + asm volatile ( + "push %%cs;" + "pop %%eax;" + /* Outputs */ : "=a" (cs) + /* Inputs */ : /* None */ + /* Clobbers */ : /* None */ + ); + + return cs; +} + +/***************************************************************************** + * Interrupt Management Functions + ****************************************************************************/ + +/* + * Initialize idt_gates with the interrupt handlers. + */ +int dbg_init_gates(void) +{ + size_t i; + uint16_t cs; + + cs = dbg_get_cs(); + for (i = 0; i < NUM_IDT_ENTRIES; i++) { + dbg_idt_gates[i].flags = 0x8E00; + dbg_idt_gates[i].segment = cs; + dbg_idt_gates[i].offset_low = + ((uint32_t)dbg_int_handlers[i] ) & 0xffff; + dbg_idt_gates[i].offset_high = + ((uint32_t)dbg_int_handlers[i] >> 16) & 0xffff; + } + + return 0; +} + +/* + * Load a new IDT. + */ +int dbg_load_idt(struct dbg_idtr *idtr) +{ + asm volatile ( + "lidt %0" + /* Outputs */ : /* None */ + /* Inputs */ : "m" (*idtr) + /* Clobbers */ : /* None */ + ); + + return 0; +} + +/* + * Get current IDT. + */ +int dbg_store_idt(struct dbg_idtr *idtr) +{ + asm volatile ( + "sidt %0" + /* Outputs */ : "=m" (*idtr) + /* Inputs */ : /* None */ + /* Clobbers */ : /* None */ + ); + + return 0; +} + +/* + * Hook a vector of the current IDT. + */ +int dbg_hook_idt(uint8_t vector, const void *function) +{ + struct dbg_idtr idtr; + struct dbg_idt_gate *gates; + + dbg_store_idt(&idtr); + gates = (struct dbg_idt_gate *)idtr.offset; + gates[vector].flags = 0x8E00; + gates[vector].segment = dbg_get_cs(); + gates[vector].offset_low = (((uint32_t)function) ) & 0xffff; + gates[vector].offset_high = (((uint32_t)function) >> 16) & 0xffff; + + return 0; +} + +/* + * Initialize IDT gates and load the new IDT. + */ +int dbg_init_idt(void) +{ + struct dbg_idtr idtr; + + dbg_init_gates(); + idtr.len = sizeof(dbg_idt_gates)-1; + idtr.offset = (uint32_t)dbg_idt_gates; + dbg_load_idt(&idtr); + + return 0; +} + +/* + * Common interrupt handler routine. + */ +void dbg_int_handler(struct dbg_interrupt_state *istate) +{ + dbg_interrupt(istate); +} + +/* + * Debug interrupt handler. + */ +void dbg_interrupt(struct dbg_interrupt_state *istate) +{ + dbg_sys_memset(&dbg_state.registers, 0, sizeof(dbg_state.registers)); + + /* Translate vector to signal */ + switch (istate->vector) { + case 1: dbg_state.signum = 5; break; + case 3: dbg_state.signum = 5; break; + default: dbg_state.signum = 7; + } + + /* Load Registers */ + dbg_state.registers[DBG_CPU_I386_REG_EAX] = istate->eax; + dbg_state.registers[DBG_CPU_I386_REG_ECX] = istate->ecx; + dbg_state.registers[DBG_CPU_I386_REG_EDX] = istate->edx; + dbg_state.registers[DBG_CPU_I386_REG_EBX] = istate->ebx; + dbg_state.registers[DBG_CPU_I386_REG_ESP] = istate->esp; + dbg_state.registers[DBG_CPU_I386_REG_EBP] = istate->ebp; + dbg_state.registers[DBG_CPU_I386_REG_ESI] = istate->esi; + dbg_state.registers[DBG_CPU_I386_REG_EDI] = istate->edi; + dbg_state.registers[DBG_CPU_I386_REG_PC] = istate->eip; + dbg_state.registers[DBG_CPU_I386_REG_CS] = istate->cs; + dbg_state.registers[DBG_CPU_I386_REG_PS] = istate->eflags; + dbg_state.registers[DBG_CPU_I386_REG_SS] = istate->ss; + dbg_state.registers[DBG_CPU_I386_REG_DS] = istate->ds; + dbg_state.registers[DBG_CPU_I386_REG_ES] = istate->es; + dbg_state.registers[DBG_CPU_I386_REG_FS] = istate->fs; + dbg_state.registers[DBG_CPU_I386_REG_GS] = istate->gs; + + dbg_main(&dbg_state); + + /* Restore Registers */ + istate->eax = dbg_state.registers[DBG_CPU_I386_REG_EAX]; + istate->ecx = dbg_state.registers[DBG_CPU_I386_REG_ECX]; + istate->edx = dbg_state.registers[DBG_CPU_I386_REG_EDX]; + istate->ebx = dbg_state.registers[DBG_CPU_I386_REG_EBX]; + istate->esp = dbg_state.registers[DBG_CPU_I386_REG_ESP]; + istate->ebp = dbg_state.registers[DBG_CPU_I386_REG_EBP]; + istate->esi = dbg_state.registers[DBG_CPU_I386_REG_ESI]; + istate->edi = dbg_state.registers[DBG_CPU_I386_REG_EDI]; + istate->eip = dbg_state.registers[DBG_CPU_I386_REG_PC]; + istate->cs = dbg_state.registers[DBG_CPU_I386_REG_CS]; + istate->eflags = dbg_state.registers[DBG_CPU_I386_REG_PS]; + istate->ss = dbg_state.registers[DBG_CPU_I386_REG_SS]; + istate->ds = dbg_state.registers[DBG_CPU_I386_REG_DS]; + istate->es = dbg_state.registers[DBG_CPU_I386_REG_ES]; + istate->fs = dbg_state.registers[DBG_CPU_I386_REG_FS]; + istate->gs = dbg_state.registers[DBG_CPU_I386_REG_GS]; +} + +/***************************************************************************** + * I/O Functions + ****************************************************************************/ + +/* + * Write to I/O port. + */ +void dbg_io_write_8(uint16_t port, uint8_t val) +{ + asm volatile ( + "outb %%al, %%dx;" + /* Outputs */ : /* None */ + /* Inputs */ : "a" (val), "d" (port) + /* Clobbers */ : /* None */ + ); +} + +/* + * Read from I/O port. + */ +uint8_t dbg_io_read_8(uint16_t port) +{ + uint8_t val; + + asm volatile ( + "inb %%dx, %%al;" + /* Outputs */ : "=a" (val) + /* Inputs */ : "d" (port) + /* Clobbers */ : /* None */ + ); + + return val; +} + +/***************************************************************************** + * NS16550 Serial Port (IO) + ****************************************************************************/ + +#define SERIAL_THR 0 +#define SERIAL_RBR 0 +#define SERIAL_LSR 5 + +int dbg_serial_getc(void) +{ + /* Wait for data */ + while ((dbg_io_read_8(SERIAL_PORT + SERIAL_LSR) & 1) == 0); + return dbg_io_read_8(SERIAL_PORT + SERIAL_RBR); +} + +int dbg_serial_putchar(int ch) +{ + /* Wait for THRE (bit 5) to be high */ + while ((dbg_io_read_8(SERIAL_PORT + SERIAL_LSR) & (1<<5)) == 0); + dbg_io_write_8(SERIAL_PORT + SERIAL_THR, ch); + return ch; +} + +/***************************************************************************** + * Debugging System Functions + ****************************************************************************/ + +/* + * Write one character to the debugging stream. + */ +int dbg_sys_putchar(int ch) +{ + return dbg_serial_putchar(ch); +} + +/* + * Read one character from the debugging stream. + */ +int dbg_sys_getc(void) +{ + return dbg_serial_getc() & 0xff; +} + +/* + * Read one byte from memory. + */ +int dbg_sys_mem_readb(address addr, char *val) +{ + *val = *(volatile char *)addr; + return 0; +} + +/* + * Write one byte to memory. + */ +int dbg_sys_mem_writeb(address addr, char val) +{ + *(volatile char *)addr = val; + return 0; +} + +/* + * Continue program execution. + */ +int dbg_sys_continue(void) +{ + dbg_state.registers[DBG_CPU_I386_REG_PS] &= ~(1<<8); + return 0; +} + +/* + * Single step the next instruction. + */ +int dbg_sys_step(void) +{ + dbg_state.registers[DBG_CPU_I386_REG_PS] |= 1<<8; + return 0; +} + +/* + * Debugger init function. + * + * Hooks the IDT to enable debugging. + */ +void dbg_start(void) +{ + /* Hook current IDT. */ + dbg_hook_idt(1, dbg_int_handlers[1]); + dbg_hook_idt(3, dbg_int_handlers[3]); + + /* Interrupt to start debugging. */ + asm volatile ("int3"); +} diff --git a/arch_x86/gdbstub_sys.h b/arch_x86/gdbstub_sys.h new file mode 100644 index 0000000..82f7ca9 --- /dev/null +++ b/arch_x86/gdbstub_sys.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2016-2019 Matt Borgerson + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef _GDBSTUB_SYS_H_ +#define _GDBSTUB_SYS_H_ + +/* Define the size_t type */ +#define DBG_DEFINE_SIZET 1 + +/* Define required standard integer types (e.g. uint16_t) */ +#define DBG_DEFINE_STDINT 1 + +/***************************************************************************** + * Types + ****************************************************************************/ + +#if DBG_DEFINE_STDINT +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; +#endif + +#if DBG_DEFINE_SIZET +typedef unsigned int size_t; +#endif + +typedef unsigned int address; +typedef unsigned int reg; + +#pragma pack(1) +struct dbg_interrupt_state { + uint32_t ss; + uint32_t gs; + uint32_t fs; + uint32_t es; + uint32_t ds; + uint32_t edi; + uint32_t esi; + uint32_t ebp; + uint32_t esp; + uint32_t ebx; + uint32_t edx; + uint32_t ecx; + uint32_t eax; + uint32_t vector; + uint32_t error_code; + uint32_t eip; + uint32_t cs; + uint32_t eflags; +}; +#pragma pack() + +#pragma pack(1) +struct dbg_idtr +{ + uint16_t len; + uint32_t offset; +}; +#pragma pack() + +#pragma pack(1) +struct dbg_idt_gate +{ + uint16_t offset_low; + uint16_t segment; + uint16_t flags; + uint16_t offset_high; +}; +#pragma pack() + +enum DBG_REGISTER { + DBG_CPU_I386_REG_EAX = 0, + DBG_CPU_I386_REG_ECX = 1, + DBG_CPU_I386_REG_EDX = 2, + DBG_CPU_I386_REG_EBX = 3, + DBG_CPU_I386_REG_ESP = 4, + DBG_CPU_I386_REG_EBP = 5, + DBG_CPU_I386_REG_ESI = 6, + DBG_CPU_I386_REG_EDI = 7, + DBG_CPU_I386_REG_PC = 8, + DBG_CPU_I386_REG_PS = 9, + DBG_CPU_I386_REG_CS = 10, + DBG_CPU_I386_REG_SS = 11, + DBG_CPU_I386_REG_DS = 12, + DBG_CPU_I386_REG_ES = 13, + DBG_CPU_I386_REG_FS = 14, + DBG_CPU_I386_REG_GS = 15, + DBG_CPU_I386_NUM_REGISTERS = 16 +}; + +struct dbg_state { + int signum; + reg registers[DBG_CPU_I386_NUM_REGISTERS]; +}; + +/***************************************************************************** + * Const Data + ****************************************************************************/ + +extern void const * const dbg_int_handlers[]; + +/***************************************************************************** + * Prototypes + ****************************************************************************/ + +int dbg_hook_idt(uint8_t vector, const void *function); +int dbg_init_gates(void); +int dbg_init_idt(void); +int dbg_load_idt(struct dbg_idtr *idtr); +int dbg_store_idt(struct dbg_idtr *idtr); +uint32_t dbg_get_cs(void); +void dbg_int_handler(struct dbg_interrupt_state *istate); +void dbg_interrupt(struct dbg_interrupt_state *istate); +void dbg_start(void); +void dbg_io_write_8(uint16_t port, uint8_t val); +uint8_t dbg_io_read_8(uint16_t port); +void *dbg_sys_memset(void *ptr, int data, size_t len); + +#endif diff --git a/x86/gdbstub_int.nasm b/x86/gdbstub_int.nasm deleted file mode 100644 index 2495971..0000000 --- a/x86/gdbstub_int.nasm +++ /dev/null @@ -1,110 +0,0 @@ -; -; Copyright (c) 2016-2019 Matt Borgerson -; -; Permission is hereby granted, free of charge, to any person obtaining a copy -; of this software and associated documentation files (the "Software"), to deal -; in the Software without restriction, including without limitation the rights -; to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -; copies of the Software, and to permit persons to whom the Software is -; furnished to do so, subject to the following conditions: -; -; The above copyright notice and this permission notice shall be included in -; all copies or substantial portions of the Software. -; -; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -; SOFTWARE. -; - -bits 32 - -%define NUM_HANDLERS 32 - -section .data -global dbg_int_handlers - -; Generate table of handlers -dbg_int_handlers: -%macro handler_addr 1 - dd dbg_int_handler_%1 -%endmacro -%assign i 0 -%rep NUM_HANDLERS - handler_addr i - %assign i i+1 -%endrep - -section .text -extern dbg_int_handler - -%macro int 1 -dbg_int_handler_%1: - push 0 ; Dummy Error code - push %1 ; Interrupt Vector - jmp dbg_int_handler_common -%endmacro - -%macro inte 1 -dbg_int_handler_%1: - ; Error code already on stack - push %1 ; Interrupt Vector - jmp dbg_int_handler_common -%endmacro - -; Generate Interrupt Handlers -%assign i 0 -%rep NUM_HANDLERS - %if (i == 8) || ((i >= 10) && (i <= 14)) || (i == 17) - inte i - %else - int i - %endif -%assign i i+1 -%endrep - -; Common Interrupt Handler -dbg_int_handler_common: - pushad - push ds - push es - push fs - push gs - push ss - mov ebp, esp - - ; Stack: - ; - EFLAGS - ; - CS - ; - EIP - ; - ERROR CODE - ; - VECTOR - ; - EAX - ; - ECX - ; - EDX - ; - EBX - ; - ESP - ; - EBP - ; - ESI - ; - EDI - ; - DS - ; - ES - ; - FS - ; - GS - ; - SS - - push ebp - call dbg_int_handler - - mov esp, ebp - pop ss - pop gs - pop fs - pop es - pop ds - popad - add esp, 8 ; Pop error & vector - iret diff --git a/x86/gdbstub_sys.c b/x86/gdbstub_sys.c deleted file mode 100644 index a73bc52..0000000 --- a/x86/gdbstub_sys.c +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Copyright (c) 2016-2019 Matt Borgerson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "gdbstub.h" - -#ifdef __STRICT_ANSI__ -#define asm __asm__ -#endif - -#define SERIAL_COM1 0x3f8 -#define SERIAL_COM2 0x2f8 -#define SERIAL_PORT SERIAL_COM1 - -#define NUM_IDT_ENTRIES 32 - -/***************************************************************************** - * BSS Data - ****************************************************************************/ - -static struct dbg_idt_gate dbg_idt_gates[NUM_IDT_ENTRIES]; -static struct dbg_state dbg_state; - -/***************************************************************************** - * Misc. Functions - ****************************************************************************/ - -void *dbg_sys_memset(void *ptr, int data, size_t len) -{ - char *p = ptr; - - while (len--) { - *p++ = (char)data; - } - - return ptr; -} - -/* - * Get current code segment (CS register). - */ -uint32_t dbg_get_cs(void) -{ - uint32_t cs; - - asm volatile ( - "push %%cs;" - "pop %%eax;" - /* Outputs */ : "=a" (cs) - /* Inputs */ : /* None */ - /* Clobbers */ : /* None */ - ); - - return cs; -} - -/***************************************************************************** - * Interrupt Management Functions - ****************************************************************************/ - -/* - * Initialize idt_gates with the interrupt handlers. - */ -int dbg_init_gates(void) -{ - size_t i; - uint16_t cs; - - cs = dbg_get_cs(); - for (i = 0; i < NUM_IDT_ENTRIES; i++) { - dbg_idt_gates[i].flags = 0x8E00; - dbg_idt_gates[i].segment = cs; - dbg_idt_gates[i].offset_low = - ((uint32_t)dbg_int_handlers[i] ) & 0xffff; - dbg_idt_gates[i].offset_high = - ((uint32_t)dbg_int_handlers[i] >> 16) & 0xffff; - } - - return 0; -} - -/* - * Load a new IDT. - */ -int dbg_load_idt(struct dbg_idtr *idtr) -{ - asm volatile ( - "lidt %0" - /* Outputs */ : /* None */ - /* Inputs */ : "m" (*idtr) - /* Clobbers */ : /* None */ - ); - - return 0; -} - -/* - * Get current IDT. - */ -int dbg_store_idt(struct dbg_idtr *idtr) -{ - asm volatile ( - "sidt %0" - /* Outputs */ : "=m" (*idtr) - /* Inputs */ : /* None */ - /* Clobbers */ : /* None */ - ); - - return 0; -} - -/* - * Hook a vector of the current IDT. - */ -int dbg_hook_idt(uint8_t vector, const void *function) -{ - struct dbg_idtr idtr; - struct dbg_idt_gate *gates; - - dbg_store_idt(&idtr); - gates = (struct dbg_idt_gate *)idtr.offset; - gates[vector].flags = 0x8E00; - gates[vector].segment = dbg_get_cs(); - gates[vector].offset_low = (((uint32_t)function) ) & 0xffff; - gates[vector].offset_high = (((uint32_t)function) >> 16) & 0xffff; - - return 0; -} - -/* - * Initialize IDT gates and load the new IDT. - */ -int dbg_init_idt(void) -{ - struct dbg_idtr idtr; - - dbg_init_gates(); - idtr.len = sizeof(dbg_idt_gates)-1; - idtr.offset = (uint32_t)dbg_idt_gates; - dbg_load_idt(&idtr); - - return 0; -} - -/* - * Common interrupt handler routine. - */ -void dbg_int_handler(struct dbg_interrupt_state *istate) -{ - dbg_interrupt(istate); -} - -/* - * Debug interrupt handler. - */ -void dbg_interrupt(struct dbg_interrupt_state *istate) -{ - dbg_sys_memset(&dbg_state.registers, 0, sizeof(dbg_state.registers)); - - /* Translate vector to signal */ - switch (istate->vector) { - case 1: dbg_state.signum = 5; break; - case 3: dbg_state.signum = 5; break; - default: dbg_state.signum = 7; - } - - /* Load Registers */ - dbg_state.registers[DBG_CPU_I386_REG_EAX] = istate->eax; - dbg_state.registers[DBG_CPU_I386_REG_ECX] = istate->ecx; - dbg_state.registers[DBG_CPU_I386_REG_EDX] = istate->edx; - dbg_state.registers[DBG_CPU_I386_REG_EBX] = istate->ebx; - dbg_state.registers[DBG_CPU_I386_REG_ESP] = istate->esp; - dbg_state.registers[DBG_CPU_I386_REG_EBP] = istate->ebp; - dbg_state.registers[DBG_CPU_I386_REG_ESI] = istate->esi; - dbg_state.registers[DBG_CPU_I386_REG_EDI] = istate->edi; - dbg_state.registers[DBG_CPU_I386_REG_PC] = istate->eip; - dbg_state.registers[DBG_CPU_I386_REG_CS] = istate->cs; - dbg_state.registers[DBG_CPU_I386_REG_PS] = istate->eflags; - dbg_state.registers[DBG_CPU_I386_REG_SS] = istate->ss; - dbg_state.registers[DBG_CPU_I386_REG_DS] = istate->ds; - dbg_state.registers[DBG_CPU_I386_REG_ES] = istate->es; - dbg_state.registers[DBG_CPU_I386_REG_FS] = istate->fs; - dbg_state.registers[DBG_CPU_I386_REG_GS] = istate->gs; - - dbg_main(&dbg_state); - - /* Restore Registers */ - istate->eax = dbg_state.registers[DBG_CPU_I386_REG_EAX]; - istate->ecx = dbg_state.registers[DBG_CPU_I386_REG_ECX]; - istate->edx = dbg_state.registers[DBG_CPU_I386_REG_EDX]; - istate->ebx = dbg_state.registers[DBG_CPU_I386_REG_EBX]; - istate->esp = dbg_state.registers[DBG_CPU_I386_REG_ESP]; - istate->ebp = dbg_state.registers[DBG_CPU_I386_REG_EBP]; - istate->esi = dbg_state.registers[DBG_CPU_I386_REG_ESI]; - istate->edi = dbg_state.registers[DBG_CPU_I386_REG_EDI]; - istate->eip = dbg_state.registers[DBG_CPU_I386_REG_PC]; - istate->cs = dbg_state.registers[DBG_CPU_I386_REG_CS]; - istate->eflags = dbg_state.registers[DBG_CPU_I386_REG_PS]; - istate->ss = dbg_state.registers[DBG_CPU_I386_REG_SS]; - istate->ds = dbg_state.registers[DBG_CPU_I386_REG_DS]; - istate->es = dbg_state.registers[DBG_CPU_I386_REG_ES]; - istate->fs = dbg_state.registers[DBG_CPU_I386_REG_FS]; - istate->gs = dbg_state.registers[DBG_CPU_I386_REG_GS]; -} - -/***************************************************************************** - * I/O Functions - ****************************************************************************/ - -/* - * Write to I/O port. - */ -void dbg_io_write_8(uint16_t port, uint8_t val) -{ - asm volatile ( - "outb %%al, %%dx;" - /* Outputs */ : /* None */ - /* Inputs */ : "a" (val), "d" (port) - /* Clobbers */ : /* None */ - ); -} - -/* - * Read from I/O port. - */ -uint8_t dbg_io_read_8(uint16_t port) -{ - uint8_t val; - - asm volatile ( - "inb %%dx, %%al;" - /* Outputs */ : "=a" (val) - /* Inputs */ : "d" (port) - /* Clobbers */ : /* None */ - ); - - return val; -} - -/***************************************************************************** - * NS16550 Serial Port (IO) - ****************************************************************************/ - -#define SERIAL_THR 0 -#define SERIAL_RBR 0 -#define SERIAL_LSR 5 - -int dbg_serial_getc(void) -{ - /* Wait for data */ - while ((dbg_io_read_8(SERIAL_PORT + SERIAL_LSR) & 1) == 0); - return dbg_io_read_8(SERIAL_PORT + SERIAL_RBR); -} - -int dbg_serial_putchar(int ch) -{ - /* Wait for THRE (bit 5) to be high */ - while ((dbg_io_read_8(SERIAL_PORT + SERIAL_LSR) & (1<<5)) == 0); - dbg_io_write_8(SERIAL_PORT + SERIAL_THR, ch); - return ch; -} - -/***************************************************************************** - * Debugging System Functions - ****************************************************************************/ - -/* - * Write one character to the debugging stream. - */ -int dbg_sys_putchar(int ch) -{ - return dbg_serial_putchar(ch); -} - -/* - * Read one character from the debugging stream. - */ -int dbg_sys_getc(void) -{ - return dbg_serial_getc() & 0xff; -} - -/* - * Read one byte from memory. - */ -int dbg_sys_mem_readb(address addr, char *val) -{ - *val = *(volatile char *)addr; - return 0; -} - -/* - * Write one byte to memory. - */ -int dbg_sys_mem_writeb(address addr, char val) -{ - *(volatile char *)addr = val; - return 0; -} - -/* - * Continue program execution. - */ -int dbg_sys_continue(void) -{ - dbg_state.registers[DBG_CPU_I386_REG_PS] &= ~(1<<8); - return 0; -} - -/* - * Single step the next instruction. - */ -int dbg_sys_step(void) -{ - dbg_state.registers[DBG_CPU_I386_REG_PS] |= 1<<8; - return 0; -} - -/* - * Debugger init function. - * - * Hooks the IDT to enable debugging. - */ -void dbg_start(void) -{ - /* Hook current IDT. */ - dbg_hook_idt(1, dbg_int_handlers[1]); - dbg_hook_idt(3, dbg_int_handlers[3]); - - /* Interrupt to start debugging. */ - asm volatile ("int3"); -} diff --git a/x86/gdbstub_sys.h b/x86/gdbstub_sys.h deleted file mode 100644 index 82f7ca9..0000000 --- a/x86/gdbstub_sys.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016-2019 Matt Borgerson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef _GDBSTUB_SYS_H_ -#define _GDBSTUB_SYS_H_ - -/* Define the size_t type */ -#define DBG_DEFINE_SIZET 1 - -/* Define required standard integer types (e.g. uint16_t) */ -#define DBG_DEFINE_STDINT 1 - -/***************************************************************************** - * Types - ****************************************************************************/ - -#if DBG_DEFINE_STDINT -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; -#endif - -#if DBG_DEFINE_SIZET -typedef unsigned int size_t; -#endif - -typedef unsigned int address; -typedef unsigned int reg; - -#pragma pack(1) -struct dbg_interrupt_state { - uint32_t ss; - uint32_t gs; - uint32_t fs; - uint32_t es; - uint32_t ds; - uint32_t edi; - uint32_t esi; - uint32_t ebp; - uint32_t esp; - uint32_t ebx; - uint32_t edx; - uint32_t ecx; - uint32_t eax; - uint32_t vector; - uint32_t error_code; - uint32_t eip; - uint32_t cs; - uint32_t eflags; -}; -#pragma pack() - -#pragma pack(1) -struct dbg_idtr -{ - uint16_t len; - uint32_t offset; -}; -#pragma pack() - -#pragma pack(1) -struct dbg_idt_gate -{ - uint16_t offset_low; - uint16_t segment; - uint16_t flags; - uint16_t offset_high; -}; -#pragma pack() - -enum DBG_REGISTER { - DBG_CPU_I386_REG_EAX = 0, - DBG_CPU_I386_REG_ECX = 1, - DBG_CPU_I386_REG_EDX = 2, - DBG_CPU_I386_REG_EBX = 3, - DBG_CPU_I386_REG_ESP = 4, - DBG_CPU_I386_REG_EBP = 5, - DBG_CPU_I386_REG_ESI = 6, - DBG_CPU_I386_REG_EDI = 7, - DBG_CPU_I386_REG_PC = 8, - DBG_CPU_I386_REG_PS = 9, - DBG_CPU_I386_REG_CS = 10, - DBG_CPU_I386_REG_SS = 11, - DBG_CPU_I386_REG_DS = 12, - DBG_CPU_I386_REG_ES = 13, - DBG_CPU_I386_REG_FS = 14, - DBG_CPU_I386_REG_GS = 15, - DBG_CPU_I386_NUM_REGISTERS = 16 -}; - -struct dbg_state { - int signum; - reg registers[DBG_CPU_I386_NUM_REGISTERS]; -}; - -/***************************************************************************** - * Const Data - ****************************************************************************/ - -extern void const * const dbg_int_handlers[]; - -/***************************************************************************** - * Prototypes - ****************************************************************************/ - -int dbg_hook_idt(uint8_t vector, const void *function); -int dbg_init_gates(void); -int dbg_init_idt(void); -int dbg_load_idt(struct dbg_idtr *idtr); -int dbg_store_idt(struct dbg_idtr *idtr); -uint32_t dbg_get_cs(void); -void dbg_int_handler(struct dbg_interrupt_state *istate); -void dbg_interrupt(struct dbg_interrupt_state *istate); -void dbg_start(void); -void dbg_io_write_8(uint16_t port, uint8_t val); -uint8_t dbg_io_read_8(uint16_t port); -void *dbg_sys_memset(void *ptr, int data, size_t len); - -#endif -- cgit v1.2.3