From ac7d5ef06a6d6e8d84abbd1f0b82162725f98326 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Thu, 11 May 1995 17:39:37 +0000 Subject: Initial revision --- cpukit/libmisc/monitor/README | 7 + cpukit/libmisc/monitor/mon-monitor.c | 307 ++++++++++++++++++++++++++++++++ cpukit/libmisc/monitor/mon-symbols.c | 327 +++++++++++++++++++++++++++++++++++ cpukit/libmisc/monitor/monitor.h | 38 ++++ cpukit/libmisc/monitor/symbols.h | 80 +++++++++ 5 files changed, 759 insertions(+) create mode 100644 cpukit/libmisc/monitor/README create mode 100644 cpukit/libmisc/monitor/mon-monitor.c create mode 100644 cpukit/libmisc/monitor/mon-symbols.c create mode 100644 cpukit/libmisc/monitor/monitor.h create mode 100644 cpukit/libmisc/monitor/symbols.h (limited to 'cpukit/libmisc/monitor') diff --git a/cpukit/libmisc/monitor/README b/cpukit/libmisc/monitor/README new file mode 100644 index 0000000000..cae39d593c --- /dev/null +++ b/cpukit/libmisc/monitor/README @@ -0,0 +1,7 @@ +# +# $Id$ +# + +This is a snapshot of a work in process. It is the beginnings of a +debug monitor task and trap handler which is tasking aware. + diff --git a/cpukit/libmisc/monitor/mon-monitor.c b/cpukit/libmisc/monitor/mon-monitor.c new file mode 100644 index 0000000000..aa466143f9 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-monitor.c @@ -0,0 +1,307 @@ +/* + * @(#)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: +} diff --git a/cpukit/libmisc/monitor/mon-symbols.c b/cpukit/libmisc/monitor/mon-symbols.c new file mode 100644 index 0000000000..58d35befa1 --- /dev/null +++ b/cpukit/libmisc/monitor/mon-symbols.c @@ -0,0 +1,327 @@ +/* + * @(#)symbols.c 1.3 - 95/04/24 + * + */ + +/* #define qsort _quicksort */ + +/* + * File: symbols.c + * + * Description: + * Symbol table manager for the RTEMS monitor. + * These routines may be used by other system resources also. + * + * + * TODO: + */ + +#include +#include +#include +#include + +#include "symbols.h" + +extern rtems_symbol_table_t *rtems_monitor_symbols; + +#ifdef RTEMS_DEBUG +#define CHK_ADR_PTR(p) \ +do { \ + if (((p) < rtems_monitor_symbols->addresses) || \ + ((p) >= (rtems_monitor_symbols->addresses + rtems_monitor_symbols->next))) \ + { \ + printf("bad address pointer %p\n", (p)); \ + rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \ + } \ +} while (0) + +#define CHK_NAME_PTR(p) \ +do { \ + if (((p) < rtems_monitor_symbols->symbols) || \ + ((p) >= (rtems_monitor_symbols->symbols + rtems_monitor_symbols->next))) \ + { \ + printf("bad symbol pointer %p\n", (p)); \ + rtems_fatal_error_occurred(RTEMS_INVALID_ADDRESS); \ + } \ +} while (0) +#else +#define CHK_ADR_PTR(p) +#define CHK_NAME_PTR(p) +#endif + +rtems_symbol_table_t * +rtems_symbol_table_create() +{ + rtems_symbol_table_t *table; + + table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t)); + memset((void *) table, 0, sizeof(*table)); + + table->growth_factor = 30; /* 30 percent */ + + return table; +} + +void +rtems_symbol_table_destroy(rtems_symbol_table_t *table) +{ + rtems_symbol_string_block_t *p, *pnext; + + if (table) + { + if (table->addresses) + (void) free(table->addresses); + table->addresses = 0; + + if (table->symbols) + (void) free(table->symbols); + table->symbols = 0; + + p = table->string_buffer_head; + while (p) + { + pnext = p->next; + free(p); + p = pnext; + } + table->string_buffer_head = 0; + table->string_buffer_current = 0; + + free(table); + } +} + +rtems_symbol_t * +rtems_symbol_create( + rtems_symbol_table_t *table, + char *name, + rtems_unsigned32 value + ) +{ + int symbol_length; + size_t newsize; + rtems_symbol_t *sp; + + symbol_length = strlen(name) + 1; /* include '\000' in length */ + + /* need to grow the table? */ + if (table->next >= table->size) + { + if (table->size == 0) + newsize = 100; + else + newsize = table->size + (table->size / (100 / table->growth_factor)); + + table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t)); + if (table->addresses == 0) /* blew it; lost orig */ + goto failed; + + table->symbols = (rtems_symbol_t *) realloc((void *) table->symbols, newsize * sizeof(rtems_symbol_t)); + if (table->symbols == 0) /* blew it; lost orig */ + goto failed; + + table->size = newsize; + } + + sp = &table->addresses[table->next]; + sp->value = value; + + /* Have to add it to string pool */ + /* need to grow pool? */ + + if ((table->string_buffer_head == 0) || + (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE) + { + rtems_symbol_string_block_t *p; + + p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t)); + if (p == 0) + goto failed; + p->next = 0; + if (table->string_buffer_head == 0) + table->string_buffer_head = p; + else + table->string_buffer_current->next = p; + table->string_buffer_current = p; + + table->strings_next = 0; + } + + sp->name = table->string_buffer_current->buffer + table->strings_next; + (void) strcpy(sp->name, name); + + table->strings_next += symbol_length; + + table->symbols[table->next] = *sp; + + table->sorted = 0; + table->next++; + + return sp; + +/* XXX Not sure what to do here. We've possibly destroyed the initial + symbol table due to realloc failure */ +failed: + return 0; +} + +/* + * Qsort entry point for compare by address + */ + +int +rtems_symbol_compare(const void *e1, + const void *e2) +{ + rtems_symbol_t *s1, *s2; + s1 = (rtems_symbol_t *) e1; + s2 = (rtems_symbol_t *) e2; + + CHK_ADR_PTR(s1); + CHK_ADR_PTR(s2); + + if (s1->value < s2->value) + return -1; + if (s1->value > s2->value) + return 1; + return 0; +} + +/* + * Qsort entry point for compare by string name (case independent) + */ + +int +rtems_symbol_string_compare(const void *e1, + const void *e2) +{ + rtems_symbol_t *s1, *s2; + s1 = (rtems_symbol_t *) e1; + s2 = (rtems_symbol_t *) e2; + + CHK_NAME_PTR(s1); + CHK_NAME_PTR(s2); + + return strcasecmp(s1->name, s2->name); +} + + +/* + * Sort the symbol table using qsort + */ + +void +rtems_symbol_sort(rtems_symbol_table_t *table) +{ +#ifdef simhppa + printf("Sorting symbols ... "); /* so slow we need a msg */ + fflush(stdout); +#endif + + qsort((void *) table->addresses, (size_t) table->next, + sizeof(rtems_symbol_t), rtems_symbol_compare); + + qsort((void *) table->symbols, (size_t) table->next, + sizeof(rtems_symbol_t), rtems_symbol_string_compare); + +#ifdef simhppa + /* so slow we need a msg */ + printf("done\n"); +#endif + + table->sorted = 1; +} + +/* + * Search the symbol table by address + * This code based on CYGNUS newlib bsearch, but changed + * to allow for finding closest symbol <= key + */ + +rtems_symbol_t * +rtems_symbol_value_lookup( + rtems_symbol_table_t *table, + rtems_unsigned32 value + ) +{ + rtems_symbol_t *sp; + rtems_symbol_t *base; + rtems_symbol_t *best = 0; + rtems_unsigned32 distance; + rtems_unsigned32 best_distance = ~0; + rtems_unsigned32 elements; + + if ((table == 0) || (table->size == 0)) + return 0; + + if (table->sorted == 0) + rtems_symbol_sort(table); + + base = table->addresses; + elements = table->next; + + while (elements) + { + sp = base + (elements / 2); + if (value < sp->value) + elements /= 2; + else if (value > sp->value) + { + distance = value - sp->value; + if (distance < best_distance) + { + best_distance = distance; + best = sp; + } + base = sp + 1; + elements = (elements / 2) - (elements % 2 ? 0 : 1); + } + else + return sp; + } + + if (value == base->value) + return base; + + return best; +} + +/* + * Search the symbol table by string name (case independent) + */ + +rtems_symbol_t * +rtems_symbol_name_lookup( + rtems_symbol_table_t *table, + char *name + ) +{ + rtems_symbol_t *sp = 0; + rtems_symbol_t key; + + if ((table == 0) || (name == 0)) + goto done; + + if (table->sorted == 0) + { + rtems_symbol_sort(table); + } + + /* + * dummy up one for bsearch() + */ + + key.name = name; + key.value = 0; + + sp = (rtems_symbol_t *) bsearch((const void *) &key, + (const void *) table->symbols, + (size_t) table->next, + sizeof(rtems_symbol_t), + rtems_symbol_string_compare); + +done: + return sp; +} + diff --git a/cpukit/libmisc/monitor/monitor.h b/cpukit/libmisc/monitor/monitor.h new file mode 100644 index 0000000000..195aa73695 --- /dev/null +++ b/cpukit/libmisc/monitor/monitor.h @@ -0,0 +1,38 @@ +/* + * @(#)monitor.h 1.2 - 95/04/24 + * + */ + +/* + * File: monitor.h + * + * Description: + * The RTEMS monitor task include file. + * + * + * + * TODO: + * + */ + +#ifndef __MONITOR_H +#define __MONITOR_H + +#ifdef __cplusplus +extern "C" { +#endif + +void rtems_monitor_init(rtems_boolean monitor_suspend); +void rtems_monitor_wakeup(void); +void rtems_monitor_task(rtems_task_argument monitor_suspend); +void rtems_monitor_symbols_loadup(void); + +extern rtems_unsigned32 rtems_monitor_task_id; + +extern rtems_symbol_table_t *rtems_monitor_symbols; + +#ifdef __cplusplus +} +#endif + +#endif /* ! __MONITOR_H */ diff --git a/cpukit/libmisc/monitor/symbols.h b/cpukit/libmisc/monitor/symbols.h new file mode 100644 index 0000000000..680ac6d2cf --- /dev/null +++ b/cpukit/libmisc/monitor/symbols.h @@ -0,0 +1,80 @@ +/* + * File: symbols.h + * + * Description: + * Entry points for symbol table routines. + * + * + * + * TODO: + * + */ + +#ifndef _INCLUDE_SYMBOLS_H +#define _INCLUDE_SYMBOLS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + rtems_unsigned32 value; + char *name; +} rtems_symbol_t; + +#define SYMBOL_STRING_BLOCK_SIZE 4080 +typedef struct rtems_symbol_string_block_s { + struct rtems_symbol_string_block_s *next; + char buffer[SYMBOL_STRING_BLOCK_SIZE]; +} rtems_symbol_string_block_t; + +typedef struct { + + rtems_unsigned32 sorted; /* are symbols sorted right now? */ + + rtems_unsigned32 growth_factor; /* % to grow by when needed */ + + rtems_unsigned32 next; /* next symbol slot to use when adding */ + rtems_unsigned32 size; /* max # of symbols */ + + /* + * Symbol list -- sorted by address (when we do a lookup) + */ + + rtems_symbol_t *addresses; /* symbol array by address */ + + /* + * String list -- sorted by name (when we do a lookup) + * This is a duplicate of the info in table->addresses, but it's + * pretty small, so I don't worry about it. + */ + + rtems_symbol_t *symbols; /* symbol array */ + + /* + * String pool, unsorted, a list of blocks of string data + */ + + rtems_symbol_string_block_t *string_buffer_head; + rtems_symbol_string_block_t *string_buffer_current; + rtems_unsigned32 strings_next; /* next byte to use in this block */ + +} rtems_symbol_table_t; + +void rtems_symbol_table_destroy(rtems_symbol_table_t *table); +rtems_symbol_table_t *rtems_symbol_table_create(); +rtems_symbol_t *rtems_symbol_create(rtems_symbol_table_t *, + char *, rtems_unsigned32); +rtems_symbol_t *rtems_symbol_value_lookup(rtems_symbol_table_t *, + rtems_unsigned32); +rtems_symbol_t *rtems_symbol_name_lookup(rtems_symbol_table_t *, + char *); + +#define rtems_symbol_name(sp) ((sp)->name) +#define rtems_symbol_value(sp) ((sp)->value) + +#ifdef __cplusplus +} +#endif + +#endif /* ! _INCLUDE_SYMBOLS_H */ -- cgit v1.2.3