From 4721cf1ecb949b37c98b6fce79163541711de2e5 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 3 Dec 1998 23:54:14 +0000 Subject: Patch from Emmanuel Raguet to add remote debug server and RPC support to RTEMS. Thanks. :) Email follows: Hello, For Xmas, here is the Remote Debugger on RTEMS ! Here are 2 patches for the Remote Debugger on RTEMS for pc386 from Linux host : - one for RTEMS it self, - one for GDB-4.17. 1/ RTEMS patch -------------- This patch adds 2 libraries : - a simplified SUN RPC library - the Remote Debugger library The configuration command is the following : ../rtems4/configure --target=i386-rtemself --enable-rtemsbsp=pc386 --enable-rdbg The SUN RPC library is built only if networking is set. The RDBG library is built if networking and enable-rdbg are set. The function used to initialize the debugger is : rtems_rdbg_initialize (); A special function has been created to force a task to be in a "debug" state : enterRdbg(). The use of this function is not mandatory. 2/ GDB-4.17 patch ----------------- This patch create a new RTEMS target for GDB-4.17. The configuration command is the following : ./configure --enable-shared --target=i386RTEMS To connect to a target, use : target rtems [your_site_address] Then, attach the target using : attach 1 And... Debug ;) You can obtain the original GDB-4.17 on ftp://ftp.debian.org/debian/dists/stable/main/source/devel/gdb_4.17.orig.tar.gz This has been tested from a Debian 2.0.1 linux host. --- c/src/librdbg/src/i386/any/remdeb_f.x | 58 ++++++++ c/src/librdbg/src/i386/excep.c | 233 ++++++++++++++++++++++++++++++++ c/src/librdbg/src/i386/pc386/remdeb_f.x | 58 ++++++++ c/src/librdbg/src/i386/rdbg_cpu_asm.s | 70 ++++++++++ c/src/librdbg/src/i386/rdbg_f.c | 130 ++++++++++++++++++ 5 files changed, 549 insertions(+) create mode 100644 c/src/librdbg/src/i386/any/remdeb_f.x create mode 100644 c/src/librdbg/src/i386/excep.c create mode 100644 c/src/librdbg/src/i386/pc386/remdeb_f.x create mode 100644 c/src/librdbg/src/i386/rdbg_cpu_asm.s create mode 100644 c/src/librdbg/src/i386/rdbg_f.c (limited to 'c/src/librdbg/src/i386') diff --git a/c/src/librdbg/src/i386/any/remdeb_f.x b/c/src/librdbg/src/i386/any/remdeb_f.x new file mode 100644 index 0000000000..0ff52d1307 --- /dev/null +++ b/c/src/librdbg/src/i386/any/remdeb_f.x @@ -0,0 +1,58 @@ +/* + ************************************************************************** + * + * Component = rdblib + * + * Synopsis = remdeb_f.x + * + * + ************************************************************************** + */ + +struct xdr_regs +{ + unsigned int tabreg[19]; +}; + +#ifdef RPC_HDR + +%/* now define register macros to apply to xdr_reg struct */ +% +%#define GS 0 +%#define FS 1 +%#define ES 2 +%#define DS 3 +%#define EDI 4 +%#define ESI 5 +%#define EBP 6 +%#define ESP 7 +%#define EBX 8 +%#define EDX 9 +%#define ECX 10 +%#define EAX 11 +%#define TRAPNO 12 +%#define ERR 13 +%#define EIP 14 +%#define CS 15 +%#define EFL 16 +%#define UESP 17 +%#define SS 18 +% +%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ +%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ +%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ + +%/* now define the BREAKPOINT mask technique to a long word */ +%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) +%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) +%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) +%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ +%#define BREAK_ADJ 1 /* must subtract one from address after bp */ +%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ + +%#define TARGET_PROC_TYPE 0 + +#endif + + + diff --git a/c/src/librdbg/src/i386/excep.c b/c/src/librdbg/src/i386/excep.c new file mode 100644 index 0000000000..5ca1fd8df6 --- /dev/null +++ b/c/src/librdbg/src/i386/excep.c @@ -0,0 +1,233 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/excep.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +extern rtems_id serializeSemId; +extern rtems_id wakeupEventSemId; + + +unsigned int NbExceptCtx; +volatile unsigned int NbSerializedCtx; +Exception_context *FirstCtx = NULL; +Exception_context *LastCtx = NULL; + +CPU_Exception_frame SavedContext; + + +/********* Save an exception context at the end of a list *****/ + +int PushExceptCtx ( Objects_Id Id, Objects_Id semId, CPU_Exception_frame *ctx ) { + + Exception_context *SaveCtx; + + SaveCtx = (Exception_context *)malloc(sizeof(Exception_context)); + if (SaveCtx == NULL) + rtems_panic("Can't allocate memory to save Exception context"); + + SaveCtx->id = Id; + SaveCtx->ctx = ctx; + SaveCtx->semaphoreId = semId; + SaveCtx->previous = NULL; + SaveCtx->next = NULL; + + if (FirstCtx == NULL){ /* initialization */ + FirstCtx = SaveCtx; + LastCtx = SaveCtx; + NbExceptCtx = 1; + } + else { + NbExceptCtx ++; + LastCtx->next = SaveCtx; + SaveCtx->previous = LastCtx; + LastCtx = SaveCtx; + } + return 0; +} + +/********* Save an temporary exception context in a ******/ +/********* global variable ******/ + +int PushSavedExceptCtx ( Objects_Id Id, CPU_Exception_frame *ctx ) { + + memcpy (&(SavedContext), ctx, sizeof(CPU_Exception_frame)); + return 0; +} + + +/****** Remove the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +int PopExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return -1; + + if (Id == -1) { + ExtractCtx = LastCtx; + LastCtx = LastCtx->previous; + free(ExtractCtx); + NbExceptCtx --; + return 0; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return -1; + + if ( ExtractCtx->previous != NULL) + (ExtractCtx->previous)->next = ExtractCtx->next; + + if ( ExtractCtx->next != NULL) + (ExtractCtx->next)->previous = ExtractCtx->previous; + + if (ExtractCtx == FirstCtx) + FirstCtx = FirstCtx->next; + else + if (ExtractCtx == LastCtx) + LastCtx = LastCtx->previous; + + free(ExtractCtx); + NbExceptCtx --; + return 0; +} + +/****** Return the context of the specified Id thread *********/ +/****** If Id = -1, then return the first context *********/ + + +Exception_context *GetExceptCtx ( Objects_Id Id ) { + + Exception_context *ExtractCtx; + + if (FirstCtx == NULL) return NULL; + + if (Id == -1) { + return LastCtx; + } + + ExtractCtx = LastCtx; + + while (ExtractCtx->id != Id && ExtractCtx != NULL) { + ExtractCtx = ExtractCtx->previous; + } + + if (ExtractCtx == NULL) + return NULL; + + return ExtractCtx; +} + +/*----- Breakpoint Exception management -----*/ + + /* + * Handler for Breakpoint Exceptions : + * software breakpoints. + */ + +void +BreakPointExcHdl(CPU_Exception_frame *ctx) +{ + rtems_status_code status; + rtems_id continueSemId; + + if ( (justSaveContext) && (ctx->idtIndex == I386_EXCEPTION_ENTER_RDBG) ) { + PushSavedExceptCtx (_Thread_Executing->Object.id, ctx); + justSaveContext = 0; + } + else { + if (ctx->idtIndex != DEBUG){ + NbSerializedCtx++; + rtems_semaphore_obtain(serializeSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + NbSerializedCtx--; + } + + currentTargetThread = _Thread_Executing->Object.id; + +#ifdef DDEBUG + printk("----------------------------------------------------------\n"); + printk("Exception %d caught at PC %x by thread %d\n", + ctx->idtIndex, + ctx->eip, + _Thread_Executing->Object.id); + printk("----------------------------------------------------------\n"); + printk("Processor execution context at time of the fault was :\n"); + printk("----------------------------------------------------------\n"); + printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n", + ctx->eax, ctx->ebx, ctx->ecx, ctx->edx); + printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n", + ctx->esi, ctx->edi, ctx->ebp, ctx->esp0); + printk("----------------------------------------------------------\n"); + printk("Error code pushed by processor itself (if not 0) = %x\n", + ctx->faultCode); + printk("----------------------------------------------------------\n\n"); +#endif + + status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'c'), + 0, + RTEMS_FIFO | + RTEMS_COUNTING_SEMAPHORE | + RTEMS_NO_INHERIT_PRIORITY | + RTEMS_NO_PRIORITY_CEILING | + RTEMS_LOCAL, + 0, + &continueSemId); + if (status != RTEMS_SUCCESSFUL) + rtems_panic ("Can't create continue semaphore: `%s'\n",rtems_status_text(status)); + + PushExceptCtx (_Thread_Executing->Object.id, continueSemId, ctx); + + switch (ctx->idtIndex){ + case I386_EXCEPTION_DEBUG: + DPRINTF((" DEBUG EXCEPTION !!!\n")); + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_BREAKPOINT: + DPRINTF((" BREAKPOINT EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + case I386_EXCEPTION_ENTER_RDBG: + DPRINTF((" ENTER RDBG !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + + default: + DPRINTF((" OTHER EXCEPTION !!!\n")); + rtems_semaphore_release( wakeupEventSemId ); + break; + } + + rtems_semaphore_obtain(continueSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); + + PopExceptCtx (_Thread_Executing->Object.id); + rtems_semaphore_delete(continueSemId); + } +} + + + diff --git a/c/src/librdbg/src/i386/pc386/remdeb_f.x b/c/src/librdbg/src/i386/pc386/remdeb_f.x new file mode 100644 index 0000000000..0ff52d1307 --- /dev/null +++ b/c/src/librdbg/src/i386/pc386/remdeb_f.x @@ -0,0 +1,58 @@ +/* + ************************************************************************** + * + * Component = rdblib + * + * Synopsis = remdeb_f.x + * + * + ************************************************************************** + */ + +struct xdr_regs +{ + unsigned int tabreg[19]; +}; + +#ifdef RPC_HDR + +%/* now define register macros to apply to xdr_reg struct */ +% +%#define GS 0 +%#define FS 1 +%#define ES 2 +%#define DS 3 +%#define EDI 4 +%#define ESI 5 +%#define EBP 6 +%#define ESP 7 +%#define EBX 8 +%#define EDX 9 +%#define ECX 10 +%#define EAX 11 +%#define TRAPNO 12 +%#define ERR 13 +%#define EIP 14 +%#define CS 15 +%#define EFL 16 +%#define UESP 17 +%#define SS 18 +% +%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ +%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ +%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ + +%/* now define the BREAKPOINT mask technique to a long word */ +%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) +%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) +%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) +%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ +%#define BREAK_ADJ 1 /* must subtract one from address after bp */ +%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ + +%#define TARGET_PROC_TYPE 0 + +#endif + + + diff --git a/c/src/librdbg/src/i386/rdbg_cpu_asm.s b/c/src/librdbg/src/i386/rdbg_cpu_asm.s new file mode 100644 index 0000000000..f0942310ce --- /dev/null +++ b/c/src/librdbg/src/i386/rdbg_cpu_asm.s @@ -0,0 +1,70 @@ +/* cpu_asm.s + * + * This file contains all assembly code for the Intel i386 implementation + * of RDBG. + * + */ + +#include + + BEGIN_CODE + +/* + * void copyback_data_cache_and_invalidate_instr_cache() + * + * This routine performs a copy of the data cache + * and invalidate the instruction cache + */ + + .p2align 1 + PUBLIC (copyback_data_cache_and_invalidate_instr_cache) + +SYM (copyback_data_cache_and_invalidate_instr_cache): + wbinvd + ret + + + +/* + * void enterRdbg(void) + * + * This function perform a call to the exception 19 + * It is used : + * 1 - in the user code, to simulate a Breakpoint. + * (with justSaveContext = 0) + * 2 - in the RDBG code, to push a ctx in the list. + * (with justSaveContext = 1) + * + * In most of case, it will be use as described in 1. + * The 2nd possibility will be used by RDBG to obtain + * its own ctx + */ + + PUBLIC (enterRdbg) + +SYM (enterRdbg): + int $50 + ret + + +/* + * void rtems_exception_prologue_50(void) + * + * Exception 50 is used to enter Rdbg + * + */ + + .p2align 4 + + PUBLIC (rtems_exception_prologue_50) + PUBLIC (_Exception_Handler) + +SYM (rtems_exception_prologue_50): + pushl $ 0 + pushl $ 50 + jmp SYM(_Exception_Handler) ; + + +END_CODE + +END diff --git a/c/src/librdbg/src/i386/rdbg_f.c b/c/src/librdbg/src/i386/rdbg_f.c new file mode 100644 index 0000000000..aeb07fcbe8 --- /dev/null +++ b/c/src/librdbg/src/i386/rdbg_f.c @@ -0,0 +1,130 @@ +/* + ************************************************************************** + * + * Component = + * + * Synopsis = rdbg/i386/rdbg_f.c + * + ************************************************************************** + */ + +#include +#include +#include +#include +#include +#include +#include + + +void +CtxToRegs (const CPU_Exception_frame* ctx, xdr_regs* regs) +{ + regs->tabreg [GS] = 0; + regs->tabreg [FS] = 0; + regs->tabreg [ES] = 0; + regs->tabreg [DS] = 0; + regs->tabreg [EDI] = ctx->edi; + regs->tabreg [ESI] = ctx->esi; + regs->tabreg [EBP] = ctx->ebp; + regs->tabreg [ESP] = ctx->esp0; + regs->tabreg [EBX] = ctx->ebx; + regs->tabreg [EDX] = ctx->edx; + regs->tabreg [ECX] = ctx->ecx; + regs->tabreg [EAX] = ctx->eax; + regs->tabreg [TRAPNO] = ctx->idtIndex; + regs->tabreg [ERR] = ctx->faultCode; + regs->tabreg [EIP] = ctx->eip; + regs->tabreg [CS] = ctx->cs & 0xFFFF; + regs->tabreg [EFL] = ctx->eflags; +} + + + void +RegsToCtx (const xdr_regs* regs, CPU_Exception_frame* ctx) +{ + ctx->edi = regs->tabreg [EDI]; + ctx->esi = regs->tabreg [ESI]; + ctx->ebp = regs->tabreg [EBP]; + ctx->esp0 = regs->tabreg [ESP]; + ctx->ebx = regs->tabreg [EBX]; + ctx->edx = regs->tabreg [EDX]; + ctx->ecx = regs->tabreg [ECX]; + ctx->eax = regs->tabreg [EAX]; + ctx->idtIndex = regs->tabreg [TRAPNO]; + ctx->faultCode = regs->tabreg [ERR]; + ctx->eip = regs->tabreg [EIP]; + ctx->cs = regs->tabreg [CS]; + ctx->eflags = regs->tabreg [EFL]; +} + +void +get_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + ctx->edi = thread->Registers.edi; + ctx->esi = thread->Registers.esi; + ctx->ebp = (unsigned32)(thread->Registers.ebp); + ctx->esp0 = (unsigned32)(thread->Registers.esp); + ctx->ebx = thread->Registers.ebx; + ctx->edx = 0; + ctx->ecx = 0; + ctx->eax = 0; + ctx->idtIndex = 0; + ctx->faultCode = 0; + ctx->eip = *(unsigned int*)(thread->Registers.esp); + ctx->cs = 0; + ctx->eflags = thread->Registers.eflags; +} + +void +set_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) +{ + thread->Registers.edi = ctx->edi; + thread->Registers.esi = ctx->esi; + thread->Registers.ebp = (void*)(ctx->ebp); + thread->Registers.esp = (void*)(ctx->esp0); + thread->Registers.ebx = ctx->ebx; + thread->Registers.eflags = ctx->eflags; +} + + + +int +Single_Step(CPU_Exception_frame* ctx) +{ + /* Check if not already set */ + if ((ctx->eflags & EFLAGS_TF) != 0 || ExitForSingleStep != 0) { + /* Check coherency */ + assert ((ctx->eflags & EFLAGS_TF) != 0); + assert (ExitForSingleStep != 0); + return 0; + } + ctx->eflags |= EFLAGS_TF; /* eflags */ + ++ExitForSingleStep; + + return 0; +} + + int +CheckForSingleStep (CPU_Exception_frame* ctx) +{ + if (ExitForSingleStep) { + /* + * This functions can be called both from + * INT1 and INT3 handlers. In case it is + * called from INT3, need to clear TF. + */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep = 0; + return 1; + } + return 0; +} + +void +CancelSingleStep (CPU_Exception_frame* ctx) +{ + /* Cancel scheduled SS */ + ctx->eflags &= ~EFLAGS_TF; + ExitForSingleStep-- ; +} -- cgit v1.2.3