source: rtems/cpukit/libmisc/monitor/mon-symbols.c @ 5e622a9

4.104.114.84.95
Last change on this file since 5e622a9 was d72caa6, checked in by Joel Sherrill <joel.sherrill@…>, on May 7, 2001 at 1:17:25 PM

2001-04-28 Ralf Corsepius <corsepiu@…>

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