source: rtems/cpukit/libmisc/monitor/mon-symbols.c @ 4bf1801

4.104.114.84.95
Last change on this file since 4bf1801 was c629812, checked in by Joel Sherrill <joel.sherrill@…>, on 12/13/99 at 22:10:45

Removed warnings.

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