summaryrefslogtreecommitdiffstats
path: root/c/src/libmisc/monitor/mon-symbols.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1995-05-11 17:39:37 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1995-05-11 17:39:37 +0000
commitac7d5ef06a6d6e8d84abbd1f0b82162725f98326 (patch)
tree9304cf759a73f2a1c6fd3191948f00e870af3787 /c/src/libmisc/monitor/mon-symbols.c
downloadrtems-ac7d5ef06a6d6e8d84abbd1f0b82162725f98326.tar.bz2
Initial revision
Diffstat (limited to 'c/src/libmisc/monitor/mon-symbols.c')
-rw-r--r--c/src/libmisc/monitor/mon-symbols.c327
1 files changed, 327 insertions, 0 deletions
diff --git a/c/src/libmisc/monitor/mon-symbols.c b/c/src/libmisc/monitor/mon-symbols.c
new file mode 100644
index 0000000000..58d35befa1
--- /dev/null
+++ b/c/src/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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rtems.h>
+
+#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;
+}
+