source: rtems/cpukit/libmisc/monitor/mon-symbols.c @ 52a0641

4.104.114.84.95
Last change on this file since 52a0641 was 8389628, checked in by Joel Sherrill <joel.sherrill@…>, on 04/22/96 at 16:53:46

updates from Tony Bennett

  • Property mode set to 100644
File size: 10.5 KB
Line 
1/*
2 *  File:       symbols.c
3 *
4 *  Description:
5 *    Symbol table manager for the RTEMS monitor.
6 *    These routines may be used by other system resources also.
7 *
8 *
9 *  TODO:
10 *
11 *  $Id$
12 */
13
14#define __RTEMS_VIOLATE_KERNEL_VISIBILITY__
15#include <rtems.h>
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20#include "monitor.h"
21#include "symbols.h"
22
23
24rtems_symbol_table_t *
25rtems_symbol_table_create()
26{
27    rtems_symbol_table_t *table;
28
29    table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
30    memset((void *) table, 0, sizeof(*table));
31
32    table->growth_factor = 30;          /* 30 percent */
33
34    return table;
35}
36
37void
38rtems_symbol_table_destroy(rtems_symbol_table_t *table)
39{
40    rtems_symbol_string_block_t *p, *pnext;
41
42    if (table)
43    {
44        if (table->addresses)
45            (void) free(table->addresses);
46        table->addresses = 0;
47        p = table->string_buffer_head;
48        while (p)
49        {
50            pnext = p->next;
51            free(p);
52            p = pnext;
53        }
54        table->string_buffer_head = 0;
55        table->string_buffer_current = 0;
56
57        free(table);
58    }
59}
60
61rtems_symbol_t *
62rtems_symbol_create(
63    rtems_symbol_table_t *table,
64    char                 *name,
65    rtems_unsigned32     value
66    )
67{
68    int symbol_length;
69    size_t newsize;
70    rtems_symbol_t *sp;
71
72    symbol_length = strlen(name) + 1;   /* include '\000' in length */
73
74    /* need to grow the table? */
75    if (table->next >= table->size)
76    {
77        if (table->size == 0)
78            newsize = 100;
79        else
80            newsize = table->size + (table->size / (100 / table->growth_factor));
81
82        table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
83        if (table->addresses == 0)        /* blew it; lost orig */
84            goto failed;
85        table->size = newsize;
86    }
87
88    sp = &table->addresses[table->next];
89    sp->value = value;
90
91    /* Have to add it to string pool */
92    /* need to grow pool? */
93
94    if ((table->string_buffer_head == 0) ||
95        (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
96    {
97        rtems_symbol_string_block_t *p;
98
99        p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
100        if (p == 0)
101            goto failed;
102        p->next = 0;
103        if (table->string_buffer_head == 0)
104            table->string_buffer_head = p;
105        else
106            table->string_buffer_current->next = p;
107        table->string_buffer_current = p;
108
109        table->strings_next = 0;
110    }
111
112    sp->name = table->string_buffer_current->buffer + table->strings_next;
113    (void) strcpy(sp->name, name);
114
115    table->strings_next += symbol_length;
116    table->sorted = 0;
117    table->next++;
118
119    return sp;
120
121/* XXX Not sure what to do here.  We've possibly destroyed the initial
122   symbol table due to realloc failure */
123failed:
124    return 0;
125}
126
127/*
128 * Qsort entry point for compare by address
129 */
130
131static int
132rtems_symbol_compare(const void *e1,
133                     const void *e2)
134{
135    rtems_symbol_t *s1, *s2;
136    s1 = (rtems_symbol_t *) e1;
137    s2 = (rtems_symbol_t *) e2;
138
139    if (s1->value < s2->value)
140        return -1;
141    if (s1->value > s2->value)
142        return 1;
143    return 0;
144}
145
146
147/*
148 * Sort the symbol table using qsort
149 */
150
151static void
152rtems_symbol_sort(rtems_symbol_table_t *table)
153{
154    qsort((void *) table->addresses, (size_t) table->next,
155          sizeof(rtems_symbol_t), rtems_symbol_compare);
156    table->sorted = 1;
157}
158
159
160/*
161 * Search the symbol table by address
162 * This code based on CYGNUS newlib bsearch, but changed
163 * to allow for finding closest symbol <= key
164 */
165
166rtems_symbol_t *
167rtems_symbol_value_lookup(
168    rtems_symbol_table_t *table,
169    rtems_unsigned32      value
170  )
171{
172    rtems_symbol_t *sp;
173    rtems_symbol_t *base;
174    rtems_symbol_t *best = 0;
175    rtems_unsigned32 distance;
176    rtems_unsigned32 best_distance = ~0;
177    rtems_unsigned32 elements;
178
179    if (table == 0)
180        table = rtems_monitor_symbols;
181
182    if ((table == 0) || (table->size == 0))
183        return 0;
184
185    if (table->sorted == 0)
186        rtems_symbol_sort(table);
187
188    base = table->addresses;
189    elements = table->next;
190
191    while (elements)
192    {
193        sp = base + (elements / 2);
194        if (value < sp->value)
195            elements /= 2;
196        else if (value > sp->value)
197        {
198            distance = value - sp->value;
199            if (distance < best_distance)
200            {
201                best_distance = distance;
202                best = sp;
203            }
204            base = sp + 1;
205            elements = (elements / 2) - (elements % 2 ? 0 : 1);
206        }
207        else
208            return sp;
209    }
210
211    if (value == base->value)
212        return base;
213
214    return best;
215}
216
217/*
218 * Search the symbol table for the exact matching address.
219 * If the symbol table has already been sorted, then
220 * call the regular symbol value lookup, however, it it
221 * has not yet been sorted, search it sequentially.
222 * This routine is primarily used for low level symbol
223 * lookups (eg. from exception handler and interrupt routines)
224 * where the penality of sorted is not wanted and where
225 * an exact match is needed such that symbol table order
226 * is not important.
227 */
228const rtems_symbol_t *
229rtems_symbol_value_lookup_exact(
230    rtems_symbol_table_t *table,
231    rtems_unsigned32      value
232  )
233{
234    int s;
235    rtems_symbol_t *sp;
236
237    if (table == 0)
238    {
239        table = rtems_monitor_symbols;
240        if (table == 0)
241            return NULL;
242    }
243   
244    if (table->sorted)
245    {
246        sp = rtems_symbol_value_lookup(table, value);
247        if ( rtems_symbol_value(sp) == value )
248            return sp;
249        else
250            return NULL;  /* not an exact match */
251    }
252 
253    for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
254    {
255        if ( sp->value == value )
256            return sp;
257    }
258
259    return NULL;
260
261}
262
263
264/*
265 * Search the symbol table by string name (case independent)
266 */
267
268rtems_symbol_t *
269rtems_symbol_name_lookup(
270    rtems_symbol_table_t *table,
271    char                 *name
272  )
273{
274    int s;
275    rtems_symbol_t *sp;
276
277    if (table == 0)
278    {
279        table = rtems_monitor_symbols;
280        if (table == 0)
281            return NULL;
282    }
283   
284    for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
285    {
286        if ( strcasecmp(sp->name, name) == 0 )
287            return sp;
288    }
289
290    return NULL;
291}
292
293void *
294rtems_monitor_symbol_next(
295    void                   *object_info,
296    rtems_monitor_symbol_t *canonical,
297    rtems_id               *next_id
298)
299{
300    rtems_symbol_table_t *table;
301    int n = rtems_get_index(*next_id);
302
303    table = *(rtems_symbol_table_t **) object_info;
304    if (table == 0)
305        goto failed;
306
307    if (n >= table->next)
308        goto failed;
309
310    /* NOTE: symbols do not have id and name fields */
311     
312    if (table->sorted == 0)
313        rtems_symbol_sort(table);
314
315    _Thread_Disable_dispatch();
316
317    *next_id += 1;
318    return (void *) (table->addresses + n);
319
320failed:
321    *next_id = RTEMS_OBJECT_ID_FINAL;
322    return 0;
323}
324
325void
326rtems_monitor_symbol_canonical(
327    rtems_monitor_symbol_t *canonical_symbol,
328    rtems_symbol_t *sp
329)
330{
331    canonical_symbol->value = sp->value;
332    canonical_symbol->offset = 0;
333    strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
334}
335
336
337void
338rtems_monitor_symbol_canonical_by_name(
339    rtems_monitor_symbol_t *canonical_symbol,
340    char                   *name
341)
342{
343    rtems_symbol_t *sp;
344
345    sp = rtems_symbol_name_lookup(0, name);
346
347    canonical_symbol->value = sp ? sp->value : 0;
348
349    strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name));
350    canonical_symbol->offset = 0;
351}
352
353void
354rtems_monitor_symbol_canonical_by_value(
355    rtems_monitor_symbol_t *canonical_symbol,
356    void                   *value_void_p
357)
358{
359    unsigned32 value = (unsigned32) value_void_p;
360    rtems_symbol_t *sp;
361
362    sp = rtems_symbol_value_lookup(0, value);
363    if (sp)
364    {
365        canonical_symbol->value = sp->value;
366        canonical_symbol->offset = value - sp->value;
367        strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name));
368    }
369    else
370    {
371        canonical_symbol->value = value;
372        canonical_symbol->offset = 0;
373        canonical_symbol->name[0] = '\0';
374    }
375}
376
377
378unsigned32
379rtems_monitor_symbol_dump(
380    rtems_monitor_symbol_t *canonical_symbol,
381    boolean                 verbose
382)
383{
384    unsigned32 length = 0;
385
386    /*
387     * print the name if it exists AND if value is non-zero
388     * Ie: don't print some garbage symbol for address 0
389     */
390
391    if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
392    {
393        if (canonical_symbol->offset == 0)
394            length += printf("%.*s",
395                             (int) sizeof(canonical_symbol->name),
396                             canonical_symbol->name);
397        else
398            length += printf("<%.*s+0x%x>",
399                             (int) sizeof(canonical_symbol->name),
400                             canonical_symbol->name,
401                             canonical_symbol->offset);
402        if (verbose)
403            length += printf(" [0x%x]", canonical_symbol->value);
404    }
405    else
406        length += printf("[0x%x]", canonical_symbol->value);
407
408    return length;
409}
410
411
412void
413rtems_monitor_symbol_dump_all(
414    rtems_symbol_table_t *table,
415    boolean               verbose
416)
417{
418    int s;
419    rtems_symbol_t *sp;
420
421    if (table == 0)
422    {
423        table = rtems_monitor_symbols;
424        if (table == 0)
425            return;
426    }
427
428    if (table->sorted == 0)
429        rtems_symbol_sort(table);
430
431    for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
432    {
433        rtems_monitor_symbol_t canonical_symbol;
434
435        rtems_monitor_symbol_canonical(&canonical_symbol, sp);
436        rtems_monitor_symbol_dump(&canonical_symbol, TRUE);
437        printf("\n");
438    }
439}
440
441
442/*
443 * 'symbol' command
444 */
445
446void
447rtems_monitor_symbol_cmd(
448    int        argc,
449    char     **argv,
450    unsigned32 command_arg,
451    boolean    verbose
452)
453{
454    int arg;
455    rtems_symbol_table_t *table;
456
457    table = *(rtems_symbol_table_t **) command_arg;
458    if (table == 0)
459    {
460        table = rtems_monitor_symbols;
461        if (table == 0)
462            return;
463    }
464
465    /*
466     * Use object command to dump out whole symbol table
467     */
468    if (argc == 1)
469        rtems_monitor_symbol_dump_all(table, verbose);
470    else
471    {
472        rtems_monitor_symbol_t canonical_symbol;
473
474        for (arg=1; argv[arg]; arg++)
475        {
476            rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
477            rtems_monitor_symbol_dump(&canonical_symbol, verbose);
478            printf("\n");
479        }
480    }
481}
Note: See TracBrowser for help on using the repository browser.