/* ============================================================================ _SERVTGT $Id$ ============================================================================ */ #include #include #include #include #include #include #include #include #include #include #ifdef DDEBUG #define Ptrace TgtDbgPtrace #else #define Ptrace TgtRealPtrace #endif extern int errno; rtems_id eventTaskId; rtems_id serializeSemId; rtems_id wakeupEventSemId; rtems_id debugId; CPU_Exception_frame Idle_frame; /* ----------------------------------------------------------------- TgtRealPtrace - lowest level ptrace() wrapper ----------------------------------------------------------------- */ int TgtRealPtrace (int req, PID aid, char *addr, int d, void *addr2) { return ptrace (req, aid, addr, d, addr2); } /* ----------------------------------------------------------------------- TgtChange() is called when the system stops. It informs the generic layers must be informed of that fact. ----------------------------------------------------------------------- */ static int TgtChange (PID pid, CPU_Exception_frame * ctx, int status) { if (TgtHandleChildChange (pid, &status, NULL, ctx)) { TgtNotifyWaitChange (pid, status, -1); } return 0; } /* ----------------------------------------------------------------------- eventTask ----------------------------------------------------------------------- */ rtems_task eventTask (rtems_task_argument pid) { Exception_context *ctx; DPRINTF (("event task: pid %d\n", pid)); /* * we spend all our time waiting for a semaphore. * If wait change, we send info */ for (;;) { DPRINTF (("Event Task: wait event\n")); rtems_semaphore_obtain (wakeupEventSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); DPRINTF (("Event Task: wake up !!!!!!!!!!!!!\n")); errno = 0; ctx = GetExceptCtx (currentTargetThread); CheckForSingleStep (ctx->ctx); TgtChange (pid, ctx->ctx, STS_MAKESIG (ExcepToSig (ctx))); } } /* ------------------------------------------------------------------- MyThreadIdle - This task is used to initiate the exception mechanism: It calls the enterDebug function with justSaveContext=1 only to push a first valid context in the list ---------------------------------------------------------------------*/ rtems_task MyThreadIdle (rtems_task_argument argument) { enterRdbg (); rtems_task_delete (RTEMS_SELF); } /* ----------------------------------------------------------------------- TgtAttach - attach to a process that is running without control. Notes: - this function performs a ptrace ATTACH equivalent (attaching to a process that we do not control now). ----------------------------------------------------------------------- */ Boolean TgtAttach (int conn_idx, /* client that is requesting */ PID pid) { /* process to attach to */ rtems_name task_name; rtems_status_code status; errno = 0; DPRINTF (("TgtAttach pid=%d\n", pid)); Ptrace (RPT_ATTACH, pid, NULL, 0, NULL); if (errno) return (False); /* failed */ TgtCreateNew (pid, conn_idx, 0, NULL, False); connect_rdbg_exception (); /* * Search for and remove debugging tasks / semaphores left over from * a previous attach without a detach. */ if (rtems_task_ident (rtems_build_name ('E', 'v', 'n', 't'), RTEMS_SEARCH_ALL_NODES, &eventTaskId) == RTEMS_SUCCESSFUL) rtems_task_delete (eventTaskId); if (rtems_semaphore_ident (rtems_build_name ('D', 'B', 'G', 's'), RTEMS_SEARCH_ALL_NODES, &serializeSemId) == RTEMS_SUCCESSFUL) rtems_semaphore_delete (serializeSemId); if (rtems_semaphore_ident (rtems_build_name ('D', 'B', 'G', 'w'), RTEMS_SEARCH_ALL_NODES, &wakeupEventSemId) == RTEMS_SUCCESSFUL) rtems_semaphore_delete (wakeupEventSemId); /* * Create the attach debugger task */ task_name = rtems_build_name ('E', 'v', 'n', 't'); if ((status = rtems_task_create (task_name, 10, 24576, RTEMS_INTERRUPT_LEVEL (0), RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK, &eventTaskId)) != RTEMS_SUCCESSFUL) { printf ("status = %d\n", status); rtems_panic ("Can't create task.\n"); } status = rtems_task_start (eventTaskId, eventTask, pid); status = rtems_semaphore_create (rtems_build_name ('D', 'B', 'G', 's'), 1, RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &serializeSemId); if (status != RTEMS_SUCCESSFUL) rtems_panic ("Can't create serialize semaphore: `%s'\n", rtems_status_text (status)); status = rtems_semaphore_create (rtems_build_name ('D', 'B', 'G', 'w'), 0, RTEMS_FIFO | RTEMS_COUNTING_SEMAPHORE | RTEMS_NO_INHERIT_PRIORITY | RTEMS_NO_PRIORITY_CEILING | RTEMS_LOCAL, 0, &wakeupEventSemId); if (status != RTEMS_SUCCESSFUL) rtems_panic ("Can't create wakeup semaphore: `%s'\n", rtems_status_text (status)); /* * Create the MyThreadIdle task to init Exception mechanism */ task_name = rtems_build_name ('R', 'i', 'n', 'i'); if ((status = rtems_task_create (task_name, 10, 24576, RTEMS_INTERRUPT_LEVEL (0), RTEMS_DEFAULT_ATTRIBUTES, &debugId)) != RTEMS_SUCCESSFUL) { printf ("status = %d (%s)\n", status, rtems_status_text (status)); rtems_panic ("Can't create task.\n"); } status = rtems_task_start (debugId, MyThreadIdle, pid); return (True); } /* ----------------------------------------------------------------------- TgtPtrace - handle ptrace requests for server. ----------------------------------------------------------------------- */ int TgtPtrace (int req, PID pid, char *addr, int data, void *addr2) { if ((req == RPT_SINGLESTEP || req == RPT_CONT) && addr2) { /* clear then step *//* addr2 is the old value */ int ret; errno = 0; TgtBreakRestoreOrig (pid, addr, addr2); ret = Ptrace (RPT_SINGLESTEP, pid, addr, data, NULL); /* step over */ if (ret) { /* error, cannot single-step */ int pid_idx = FindPidEntry (pid); TgtBreakCancelStep (&pid_list[pid_idx]); } return (ret); /* failed or done */ } else return (Ptrace (req, pid, addr, data, addr2)); /* normal call */ } /* ----------------------------------------------------------------- TgtGetThreadName - get thread name --------------------------------------------------------------- */ int TgtGetThreadName (PID_LIST * plst, /* Process entry */ unsigned Id, /* Thread ID */ char *ThrName) { /* Thread name */ int index; unsigned name; 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; name = *(unsigned *) (_Objects_Information_table[OBJECTS_CLASSIC_API][1]-> local_table[1 + index]->name); ThrName[0] = (char) ((name >> 24) & 0xFF); ThrName[1] = (char) ((name >> 16) & 0xFF); ThrName[2] = (char) ((name >> 8) & 0xFF); ThrName[3] = (char) (name & 0xFF); ThrName[4] = 0x0; return 0; } 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; name = *(unsigned *) (_Objects_Information_table[OBJECTS_POSIX_API][1]-> local_table[1 + index]->name); ThrName[0] = (char) ((name >> 24) & 0xFF); ThrName[1] = (char) ((name >> 16) & 0xFF); ThrName[2] = (char) ((name >> 8) & 0xFF); ThrName[3] = (char) (name & 0xFF); ThrName[4] = 0x0; return 0; } return -1; } /* ----------------------------------------------------------------- TgtThreadList - return all the threads in the system ----------------------------------------------------------------- */ int TgtThreadList (PID_LIST * plst, /* Process entry */ unsigned *threads, /* Output buffer */ unsigned size) { /* Output buffer size */ int curr = 0; int api; Objects_Id id, min_id, max_id; unsigned index; for ( api=OBJECTS_CLASSIC_API ; api <= OBJECTS_ITRON_API ; api++ ) { min_id = _Objects_Information_table[api][1]->minimum_id; max_id = _Objects_Information_table[api][1]->maximum_id; id = min_id; while (id < max_id) { index = id - min_id; if (_Objects_Information_table[api][1]->local_table[1 + index] != NULL) { threads[curr] = (unsigned) id; curr++; } id++; } } return curr; }