source: rtems/cpukit/libmisc/monitor/mon-symbols.c @ 6425dc5

4.115
Last change on this file since 6425dc5 was 6425dc5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 12/06/11 at 07:34:48

2011-12-06 Ralf Corsépius <ralf.corsepius@…>

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