📄 i386_stub.c
字号:
/* i386_stub.c - helper functions for stub, generic to all i386 processors * * Copyright (c) 1998,1999, 2001 Cygnus Solutions * * The authors hereby grant permission to use, copy, modify, distribute, * and license this software and its documentation for any purpose, provided * that existing copyright notices are retained in all copies and that this * notice is included verbatim in any distributions. No written agreement, * license, or royalty fee is required for any of the authorized uses. * Modifications to this software may be copyrighted by their authors * and need not follow the licensing terms described here, provided that * the new terms are clearly indicated on the first page of each file where * they apply. *//*- pjo, 29 sep 1999- Copied from the ARM configuration and merged with an older GDB i386-stub.c.*/#include <stddef.h>#include <pkgconf/hal.h>#ifdef CYGPKG_REDBOOT#include <pkgconf/redboot.h>#endif#ifdef CYGPKG_HAL_I386_SIM#error "GDB Stub support not implemented for i386 SIM"#endif#include <cyg/hal/hal_stub.h>#include <cyg/hal/hal_arch.h>#include <cyg/hal/hal_intr.h>#include <cyg/hal/i386_stub.h>#ifndef FALSE#define FALSE 0#define TRUE 1#endif#ifdef CYGDBG_HAL_DEBUG_GDB_THREAD_SUPPORT#include <cyg/hal/dbg-threads-api.h> // dbg_currthread_id#endif// We need a local memcpy so we don't rely on libc.static inline void*memcpy(void* dest, void* src, int size){ unsigned char* __d = (unsigned char*) dest; unsigned char* __s = (unsigned char*) src; while(size--) *__d++ = *__s++; return dest;}#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS/* Given a trap value TRAP, return the corresponding signal. */int __computeSignal (unsigned int trap_number){ switch (trap_number) { case CYGNUM_HAL_VECTOR_DIV0: /* This isn't quite accurrate: this is integer division only. */ return SIGFPE ; case CYGNUM_HAL_VECTOR_DEBUG: return SIGTRAP ; case CYGNUM_HAL_VECTOR_NMI: return SIGINT ; case CYGNUM_HAL_VECTOR_BREAKPOINT: return SIGTRAP ; case CYGNUM_HAL_VECTOR_OVERFLOW: case CYGNUM_HAL_VECTOR_BOUND: return SIGSEGV ; case CYGNUM_HAL_VECTOR_OPCODE: return SIGILL ; case CYGNUM_HAL_VECTOR_NO_DEVICE: case CYGNUM_HAL_VECTOR_FPE: return SIGFPE ; case CYGNUM_HAL_VECTOR_DOUBLE_FAULT: return SIGTRAP ; case CYGNUM_HAL_VECTOR_INVALID_TSS: case CYGNUM_HAL_VECTOR_SEGV: case CYGNUM_HAL_VECTOR_STACK_FAULT: case CYGNUM_HAL_VECTOR_PROTECTION: case CYGNUM_HAL_VECTOR_PAGE: case CYGNUM_HAL_VECTOR_ALIGNMENT: return SIGSEGV ; default: return SIGTRAP; }}/* Return the trap number corresponding to the last-taken trap. */int __get_trap_number (void){#if 1 // The vector is not not part of the GDB register set so get it // directly from the HAL saved context. return _hal_registers->vector;#else extern int hal_pc_trap_number ; // The vector is not not part of the GDB register set so get it // directly from the save context. return hal_pc_trap_number ;#endif }#if defined(CYGSEM_REDBOOT_BSP_SYSCALLS)int __is_bsp_syscall(void) { return __get_trap_number() == 0x80;}#endif/* Set the currently-saved pc register value to PC. */void set_pc (target_register_t pc){ put_register (PC, pc);}static target_register_treg_offset(regnames_t reg){ switch(reg) { case EAX ... GS: return reg * 4;#ifdef CYGHWR_HAL_I386_FPU case REG_FST0 ... REG_FST7: return (target_register_t)&((GDB_SavedRegisters *)0)->st0[0] + ((reg - REG_FST0) * 10); case REG_FCTRL: return (target_register_t)&((GDB_SavedRegisters *)0)->fcw; case REG_FSTAT: return (target_register_t)&((GDB_SavedRegisters *)0)->fsw; case REG_FTAG: return (target_register_t)&((GDB_SavedRegisters *)0)->ftw; case REG_FISEG: case REG_FOP: // REG_FISEG is lsw, REG_FOP is msw return (target_register_t)&((GDB_SavedRegisters *)0)->cssel; case REG_FIOFF: return (target_register_t)&((GDB_SavedRegisters *)0)->ipoff; case REG_FOSEG: return (target_register_t)&((GDB_SavedRegisters *)0)->opsel; case REG_FOOFF: return (target_register_t)&((GDB_SavedRegisters *)0)->dataoff;#endif#if 0 // GDB never asks for MMX regs directly, but it did... case REG_MMX0 ... REG_MMX7: { target_register_t tos = (get_register (REG_FSTAT) >> 11) & 7; return reg_offset((((8 - tos) + reg - REG_MMX0) & 7) + REG_FST0); }#endif#ifdef CYGHWR_HAL_I386_PENTIUM_SSE case REG_XMM0 ... REG_XMM7: return (target_register_t)&((GDB_SavedRegisters *)0)->xmm0[0] + ((reg - REG_XMM0) * 16); case REG_MXCSR: return (target_register_t)&((GDB_SavedRegisters *)0)->mxcsr;#endif#ifdef CYGHWR_HAL_I386_PENTIUM_GDB_REGS case REG_CR0 ... REG_CR4: return (target_register_t)&((GDB_SavedRegisters *)0)->cr0 + ((reg - REG_CR0) * 4); case REG_GDT: return (target_register_t)&((GDB_SavedRegisters *)0)->gdtr[0]; case REG_IDT: return (target_register_t)&((GDB_SavedRegisters *)0)->idtr[0];#endif default: return -1; } return -1;}// Return the currently-saved value corresponding to register REG of// the exception context.target_register_t get_register (regnames_t reg){ target_register_t val; target_register_t offset = reg_offset(reg); if (REGSIZE(reg) > sizeof(target_register_t) || offset == -1) return -1; val = _registers[offset/sizeof(target_register_t)];#ifdef CYGHWR_HAL_I386_FPU if (reg == REG_FISEG) val &= 0xffff; else if (reg == REG_FOP) val = (val >> 16) & 0xffff;#endif return val;}// Store VALUE in the register corresponding to WHICH in the exception// context.void put_register (regnames_t which, target_register_t value){ target_register_t index; target_register_t offset = reg_offset(which); if (REGSIZE(which) > sizeof(target_register_t) || offset == -1) return; index = offset / sizeof(target_register_t); switch (which) {#ifdef CYGHWR_HAL_I386_FPU case REG_FISEG: value = (_registers[index] & 0xffff0000) | (value & 0xffff); break; case REG_FOP: value = (_registers[index] & 0x0000ffff) | (value << 16); break;#endif#ifdef CYGHWR_HAL_I386_PENTIUM_GDB_REGS case REG_CR0: value &= REG_CR0_MASK; break; case REG_CR2: value &= REG_CR2_MASK; break; case REG_CR3: value &= REG_CR3_MASK; break; case REG_CR4: value &= REG_CR4_MASK; break;#endif default: break; } _registers[index] = value;}#ifdef CYGHWR_HAL_I386_PENTIUM_GDB_REGS// Handle the Model Specific Registersstatic target_register_t _msrval[2];static int _which_msr = 0;static int _dummy_flag = 0;extern void * volatile __mem_fault_handler;static void__do_read_msr (void){ // _dummy_flag is always false but the goto is necessary to keep // some compilers from reordering stuff across the 'err' label. if (_dummy_flag) goto err; __mem_fault = 1; // Defaults to 'fail'. Is cleared // when the wrmsr completes. __mem_fault_handler = &&err; asm volatile ("movl %2,%%ecx\n" "rdmsr\n" "movl %%edx,%1\n" "movl %%eax,%0\n" : "=m" (_msrval[0]), "=m" (_msrval[1]) : "m" (_which_msr) : "ecx", "ebx", "edx", "eax", "memory"); __mem_fault = 0; err: __mem_fault_handler = (void *)0;}static void__do_write_msr (void){ // _dummy_flag is always false but the goto is necessary to keep // some compilers from reordering stuff across the 'err' label. if (_dummy_flag) goto err; __mem_fault = 1; // Defaults to 'fail'. Is cleared // when the wrmsr completes. __mem_fault_handler = &&err; asm volatile ("movl %1,%%edx\n" "movl %0,%%eax\n" "movl %2,%%ecx\n" "wrmsr\n" : /* no outputs */ : "m" (_msrval[0]), "m" (_msrval[1]), "m" (_which_msr) : "ecx", "ebx", "edx", "eax", "memory"); __mem_fault = 0; err: __mem_fault_handler = (void *)0;}static intrdmsr (int msrnum, target_register_t *msrval){ _which_msr = msrnum; __set_mem_fault_trap (__do_read_msr); if (__mem_fault) return 0; msrval[0] = _msrval[0]; msrval[1] = _msrval[1]; return 1;}static intwrmsr (int msrnum, target_register_t *msrval){ _which_msr = msrnum;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -