summaryrefslogblamecommitdiffstats
path: root/c/src/librdbg/src/ptrace.c
blob: 1286b507dd85baf73ea3fdd2fca2216eeb380c80 (plain) (tree)
1
2
3
4
5
6
7
8
9






                                                                           

       




















                                                                           
                                                                    


















































































































                                                                                                         
                                                                         


















                                                    
                                 





































































































































































                                                                      
/*
 **************************************************************************
 *
 * Component =   
 * 
 * Synopsis  =   rkdb/rkdb.c
 *
 * $Id$
 *
 **************************************************************************
 */

#include <assert.h>
#include <errno.h>
#include <rdbg/rdbg.h>
#include <rdbg/rdbg_f.h>
#include <rdbg/servrpc.h>

extern rtems_id serializeSemId;
extern rtems_id wakeupEventSemId;
extern rtems_id eventTaskId;
extern Exception_context *FirstCtx;
extern Exception_context *LastCtx;
extern CPU_Exception_frame SavedContext;
extern unsigned int NbExceptCtx;
extern unsigned int NbSerializedCtx;         



/* --------------------------------------------------------------------
   return a pointer to the Thread Control structure of the specified
   Id
   -------------------------------------------------------------------- */

Thread_Control *Thread_Get_RDBG (
  Objects_Id           Id
)
{
  unsigned index;

  if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id &&
       Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) {

    index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id;
    if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL) {
      return (Thread_Control *)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]);
    }
  }
  
  if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id &&
       Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) {

    index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id;
    if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL)
      return (Thread_Control *)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]);
  }

  return 0;

}


/* --------------------------------------------------------------------
   Memory read
   -------------------------------------------------------------------- */

int
safeMemRead(void *src, void *dest, int nbBytes){

  /*
   * safe because if it generates an exception,
   * it must return normally
   * TBD
   */

  memcpy(dest, src, nbBytes);
  return 0;
}

/* --------------------------------------------------------------------
   Memory write
   -------------------------------------------------------------------- */
int
safeMemWrite(void *src, void * dest, int nbBytes){

  /*
   * safe because if it generates an exception,
   * it must return normally
   * TBD
   */
  
  memcpy(dest, src, nbBytes);
  return 0; 
}

/* --------------------------------------------------------------------
   Ptrace
   -------------------------------------------------------------------- */

int
ptrace (int request, int pid, char* addr, int data, char* addr2)
 { 
   int diag; 
   errno = 0 ; 
   if (pid != 1) { 
     errno = ESRCH; 
     return -1; 
   } 
   switch (request) { 

   case RPT_SINGLESTEP:{
     Exception_context *ctx;

     if (CannotRestart == 1){
       setErrno(EIO);
       return -1;
     }
     
     if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { 
       Single_Step(ctx->ctx);
       rtems_semaphore_release( ctx->semaphoreId );
       return 0;
     }
     break;
   }

   case RPT_PEEKTEXT: 
   case RPT_PEEKDATA: { 
     diag = safeMemRead(addr, &data, sizeof data); 
     if (diag == 0) return data; 
   mem_error: 
     return -1; 
   } 

   case RPT_POKETEXT: {
     diag = safeMemWrite(&data, addr, sizeof data); 

     /*
      * We must flush the INSTR and DATA cache to be sure the
      *	opcode modification is taken into account, because
      *	the breakpoint opcode is written via the data cache
      *	while execution code is fetched via the instruction
      *	cache
      */
     
     if (diag == 0) {
       copyback_data_cache_and_invalidate_instr_cache(addr, sizeof data);
       return 0;
     }
     goto mem_error; 
   } 
   case RPT_POKEDATA: { 
     diag = safeMemWrite(&data, addr, sizeof data); 
     if (diag == 0) return 0; 
     goto mem_error; 
   } 
   case RPT_CONT: {
     Exception_context *ctx;

     if (CannotRestart == 1){
       setErrno (EIO);
       return -1;
     }
             
     ctx = GetExceptCtx (currentTargetThread);

     if (!isRdbgException(ctx)) {
       CannotRestart = 1;
       setErrno (EIO);
       return -1;
     }

     assert (data == 0);
     assert (ExitForSingleStep == 0);

     rtems_semaphore_release( serializeSemId );

     if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { 
       rtems_semaphore_release( ctx->semaphoreId );
     }
     return 0;
   }
     
   case RPT_ATTACH: 
     return 0; 
     
   case RPT_DETACH:{
     Exception_context *ctx;
     
     if (NbExceptCtx || NbSerializedCtx) {
       ctx = FirstCtx;
       rtems_task_delete(eventTaskId);
       rtems_semaphore_delete(serializeSemId);
       rtems_semaphore_delete(wakeupEventSemId);
     } 
     return 0;
   }
     
   case RPT_GETREGS:{ 
     Exception_context *ctx;

     if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { 
       CtxToRegs (ctx->ctx, (xdr_regs*) addr); 
       return 0; 
     } 
     break; 
   }

   case RPT_SETREGS:{ 
     Exception_context *ctx;

     if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { 
       RegsToCtx ((xdr_regs*) addr, ctx->ctx); 
       return 0;
     }
     break;
   }
 
   case RPT_READTEXT: 
   case RPT_READDATA: { 
     diag = safeMemRead(addr, addr2, data); 
     if (diag == 0) return 0; 
     goto mem_error;
   } 
   case RPT_WRITETEXT: 
   case RPT_WRITEDATA: { 
     diag = safeMemWrite(addr2, addr, data); 
     if (diag == 0) return 0; 
     goto mem_error; 
   } 
   
   case RPT_GETTARGETTHREAD: 
     if (!NbExceptCtx) { 
       errno = EBUSY; 
       return -1; 
     }       
     return currentTargetThread;

   case RPT_SETTARGETTHREAD: 
     if (!NbExceptCtx) { 
       errno = EBUSY; 
       return -1; 
     }
     currentTargetThread = data;
     return 0;
     
   case RPT_GETTHREADNAME: { 
     return TgtGetThreadName (NULL, (unsigned)(data), (char *) addr); 
   } 	
   
   case RPT_THREADLIST: { 
     int count = TgtThreadList (NULL, (unsigned*) addr, UTHREAD_MAX 
				* sizeof (unsigned)); 
     if (count < 0) { 	
       errno = EINVAL; 	
       return -1; 	
     } 	
     return count; 
   } 	

   case RPT_SETTHREADREGS: { 
     Exception_context *ctx;
     CPU_Exception_frame Ectx;
     Thread_Control *thread;
     rtems_id id;
          
     rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id);
     if (data == (unsigned)id)
       break;
     
     if ((ctx = GetExceptCtx (data)) != NULL) { 
       RegsToCtx ((xdr_regs*) addr, ctx->ctx); 
       return 0; 
     }
     thread = Thread_Get_RDBG ((Objects_Id)(data));
     if (thread != NULL) {
       RegsToCtx ((xdr_regs*) addr, &Ectx); 
       set_ctx_thread (thread, &Ectx);
       return 0; 
     }
     break; 
   }

   case RPT_GETTHREADREGS: { 
     Exception_context *ctx;
     CPU_Exception_frame Ectx;
     Thread_Control *thread;
     rtems_id id;
          
     rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id);
     if (data == (unsigned)id){
       justSaveContext = 1;
       enterRdbg();
       CtxToRegs (&(SavedContext), (xdr_regs*) addr); 
       return 0; 
     }
     
     if ((ctx = GetExceptCtx (data)) != NULL) { 
       CtxToRegs (ctx->ctx, (xdr_regs*) addr); 
       return 0; 
     }
     thread = Thread_Get_RDBG ((Objects_Id)(data));
     if (thread != NULL) {
       get_ctx_thread (thread, &Ectx);
       CtxToRegs (&Ectx, (xdr_regs*) addr); 
       return 0; 
     }       
     break; 
   }
   
   case RPT_KILL:
     TotalReboot = 1;
     return 0;

   case RPT_TRACEME: 
   case RPT_PEEKUSER: 
   case RPT_POKEUSER: 
   case RPT_GETFPREGS: 
   case RPT_SETFPREGS:
   case RPT_GETFPAREGS:
   case RPT_SETFPAREGS:
   case RPT_SYSCALL:
   case RPT_DUMPCORE:
   case RPT_GETUCODE:
   case RPT_THREADSUSPEND:
   case RPT_THREADRESUME:
   case RPT_SETTHREADNAME:
   default:
     break;
   }
   errno = EINVAL;
   return -1;
}