summaryrefslogblamecommitdiffstats
path: root/c/src/librdbg/src/ptrace.c
blob: d3603e44899459942e8bd577881b31c1437a9d57 (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 rtems_id debugId;
extern Exception_context *FirstCtx;
extern Exception_context *LastCtx;
extern CPU_Exception_frame SavedContext;
extern unsigned int NbExceptCtx;

/* 
 * 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_CLASSIC_API][1]->maximum_id &&
      Id > _Objects_Information_table[OBJECTS_CLASSIC_API][1]->minimum_id) {

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

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

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

  return 0;

}

  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;
}

  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;
}

  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 (ctx == NULL)
        ctx = GetExceptCtx (debugId);

      if (ctx != NULL) {

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

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

        rtems_semaphore_release (ctx->semaphoreId);
      }
      rtems_semaphore_release (serializeSemId);
      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;
}