summaryrefslogblamecommitdiffstats
path: root/c/src/librdbg/src/i386/excep.c
blob: 497c804e70d6a18f0a2ec36206d47b0c44e66fcc (plain) (tree)






























































































































































                                                                                 
                                               








































































                                                                                        
/*
 **************************************************************************
 *
 * 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 != I386_EXCEPTION_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);
  }
}