summaryrefslogtreecommitdiffstats
path: root/c/src/librdbg/src/i386
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1998-12-03 23:54:14 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1998-12-03 23:54:14 +0000
commit4721cf1ecb949b37c98b6fce79163541711de2e5 (patch)
treea89f2bef604b2ddf22b262fe6115d9f75c952781 /c/src/librdbg/src/i386
parentRemoved spaces. (diff)
downloadrtems-4721cf1ecb949b37c98b6fce79163541711de2e5.tar.bz2
Patch from Emmanuel Raguet <raguet@crf.canon.fr> 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.
Diffstat (limited to 'c/src/librdbg/src/i386')
-rw-r--r--c/src/librdbg/src/i386/any/remdeb_f.x58
-rw-r--r--c/src/librdbg/src/i386/excep.c233
-rw-r--r--c/src/librdbg/src/i386/pc386/remdeb_f.x58
-rw-r--r--c/src/librdbg/src/i386/rdbg_cpu_asm.s70
-rw-r--r--c/src/librdbg/src/i386/rdbg_f.c130
5 files changed, 549 insertions, 0 deletions
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 <rtems.h>
+#include <rtems/error.h>
+#include <rdbg/rdbg_f.h>
+#include <assert.h>
+#include <errno.h>
+#include <rdbg/rdbg.h>
+#include <rdbg/servrpc.h>
+
+
+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 <asm.h>
+
+ 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 <assert.h>
+#include <errno.h>
+#include <rdbg/reg.h>
+#include <rdbg/remdeb.h>
+#include <rdbg/rdbg.h>
+#include <rtems/score/cpu.h>
+#include <rtems/score/thread.h>
+
+
+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-- ;
+}