/* * @(#)monitor.c 1.6 - 95/04/24 * */ /* * mon-task.c * * Description: * RTEMS monitor task * * * * TODO: * add pause command (monitor sleeps for 'n' ticks, then wakes up) * */ #include /* #include */ #include "symbols.h" #include "monitor.h" #include #include #include #include #define STREQ(a,b) (strcmp(a,b) == 0) /* set by trap handler */ extern rtems_tcb *debugger_interrupted_task; extern rtems_context *debugger_interrupted_task_context; extern rtems_unsigned32 debugger_trap; /* our task id needs to be public so any debugger can resume us */ rtems_unsigned32 rtems_monitor_task_id; rtems_symbol_table_t *rtems_monitor_symbols; #ifndef MONITOR_PROMPT #define MONITOR_PROMPT "rtems> " #endif #define MONITOR_WAKEUP_EVENT RTEMS_EVENT_0 /* * Function: rtems_monitor_init * * Description: * Create the RTEMS monitor task * * Parameters: * 'monitor_suspend' arg is passed as initial arg to monitor task * If TRUE, monitor will suspend itself as it starts up. Otherwise * it will begin its command loop. * * Returns: * * * Side Effects: * * * Notes: * * * Deficiencies/ToDo: * * */ /* * make_argv(cp): token-count * Break up the command line in 'cp' into global argv[] and argc (return * value). */ int rtems_monitor_make_argv( char *cp, int *argc_p, char **argv) { int argc = 0; while ((cp = strtok(cp, " \t\n\r"))) { argv[argc++] = cp; cp = (char *) NULL; } argv[argc] = (char *) NULL; /* end of argv */ return *argc_p = argc; } void rtems_monitor_init(rtems_boolean monitor_suspend) { rtems_status_code status; status = rtems_task_create(rtems_build_name('R', 'M', 'O', 'N'), 1, 0/*stack*/, RTEMS_NO_PREEMPT | RTEMS_INTERRUPT_LEVEL(0), RTEMS_DEFAULT_ATTRIBUTES, &rtems_monitor_task_id); if (status != RTEMS_SUCCESSFUL) { printf("could not create monitor task\n"); goto done; } rtems_monitor_symbols_loadup(); status = rtems_task_start(rtems_monitor_task_id, rtems_monitor_task, monitor_suspend); if (status != RTEMS_SUCCESSFUL) { printf("could not start monitor!\n"); goto done; } done: } rtems_status_code rtems_monitor_suspend(rtems_interval timeout) { rtems_event_set event_set; rtems_status_code status; status = rtems_event_receive(MONITOR_WAKEUP_EVENT, RTEMS_DEFAULT_OPTIONS, timeout, &event_set); return status; } void rtems_monitor_wakeup(void) { rtems_status_code status; status = rtems_event_send(rtems_monitor_task_id, MONITOR_WAKEUP_EVENT); } /* * Read and break up a monitor command * * We have to loop on the gets call, since it will return NULL under UNIX * RTEMS when we get a signal (eg: SIGALRM). */ int rtems_monitor_read_command(char *command, int *argc, char **argv) { printf("%s", MONITOR_PROMPT); fflush(stdout); while (gets(command) == (char *) 0) ; return rtems_monitor_make_argv(command, argc, argv); } void rtems_monitor_task(rtems_task_argument monitor_suspend) { rtems_tcb *debugee = 0; char command[513]; rtems_context *rp; rtems_context_fp *fp; char *cp; int argc; char *argv[64]; if ((rtems_boolean) monitor_suspend) (void) rtems_monitor_suspend(RTEMS_NO_TIMEOUT); for (;;) { extern rtems_tcb * _Thread_Executing; debugee = _Thread_Executing; rp = &debugee->Registers; fp = (rtems_context_fp *) debugee->fp_context; /* possibly 0 */ if (0 == rtems_monitor_read_command(command, &argc, argv)) continue; if (STREQ(argv[0], "quit")) rtems_monitor_suspend(RTEMS_NO_TIMEOUT); else if (STREQ(argv[0], "pause")) rtems_monitor_suspend(1); #ifdef CPU_INVOKE_DEBUGGER else if (STREQ(argv[0], "debug")) { CPU_INVOKE_DEBUGGER; } #endif else if (STREQ(argv[0], "symbol")) { char *symbol; char *value; if (argc != 3) { printf("usage: symbol symname symvalue\n"); continue; } symbol = argv[1]; value = argv[2]; if (symbol && value) { rtems_symbol_t *sp; sp = rtems_symbol_create(rtems_monitor_symbols, symbol, (rtems_unsigned32) strtoul(value, 0, 16)); if (sp) printf("symbol defined is at %p\n", sp); else printf("could not define symbol\n"); } else printf("parsing error\n"); } else { printf("Unrecognized command: '%s'\n", argv[0]); } } } /* * Function: rtems_monitor_symbols_loadup * * Description: * Create and load the monitor's symbol table. * We are reading the output format of 'gnm' which looks like this: * * 400a7068 ? _Rate_monotonic_Information * 400a708c ? _Thread_Dispatch_disable_level * 400a7090 ? _Configuration_Table * * * We ignore the type field. * * Parameters: * * * Returns: * * * Side Effects: * Creates and fills in 'rtems_monitor_symbols' table * * Notes: * * * Deficiencies/ToDo: * Someday this should know BFD * Maybe we could get objcopy to just copy the symbol areas * and copy that down. * */ void rtems_monitor_symbols_loadup(void) { FILE *fp; char buffer[128]; rtems_monitor_symbols = rtems_symbol_table_create(10); if (rtems_monitor_symbols == 0) return; fp = fdopen(8, "r"); if (fp == 0) return; while (fgets(buffer, sizeof(buffer) - 1, fp)) { char *symbol; char *value; char *ignored_type; value = strtok(buffer, " \t\n"); ignored_type = strtok(0, " \t\n"); symbol = strtok(0, " \t\n"); if (symbol && ignored_type && value) { rtems_symbol_t *sp; sp = rtems_symbol_create(rtems_monitor_symbols, symbol, (rtems_unsigned32) strtoul(value, 0, 16)); if (sp == 0) { printf("could not define symbol\n"); goto done; } } else { printf("parsing error\n"); goto done; } } done: }