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

5
Last change on this file since f97536d was f97536d, checked in by Sebastian Huber <sebastian.huber@…>, on 10/16/15 at 06:21:48

basdefs.h: Add and use RTEMS_UNUSED

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