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

Last change on this file was e4cc56a7, checked in by Joel Sherrill <joel@…>, on 03/24/22 at 17:37:47

cpukit/libmisc/monitor/: Manually change to BSD-2 license

This code did not have any copyrights or licenses and a bit
of archeology was needed to determine authorship.

This code was in the initial import into the RTEMS CVS repository when
it was established in May 1995. There was very little, if any, code not
written by OAR Corporation in that initial import. After discussion
with Chris Johns, it was determined that this code was from OAR
Corporation and that he had added a few features later. Both
Chris Johns and OAR Corporation have given permission to relicense.

Updates #3053.

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