/* ************************************************************************** * * Component = * * Synopsis = rkdb/rkdb.c * * $Id$ * ************************************************************************** */ #include #include #include #include #include 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; }