Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:18

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @brief Symbol table manager for the RTEMS monitor
0007  *
0008  * These routines may be used by other system resources also.
0009  */
0010 
0011 /*
0012  * COPYRIGHT (c) 1989-2022. On-Line Applications Research Corporation (OAR).
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
0024  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
0027  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
0028  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
0029  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
0032  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
0033  * POSSIBILITY OF SUCH DAMAGE.
0034  */
0035 
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039 
0040 #include <string.h>
0041 #ifdef HAVE_STRINGS_H
0042 #include <strings.h>
0043 #endif
0044 
0045 #include <rtems.h>
0046 #include <stdio.h>
0047 #include <stdlib.h>
0048 #include <inttypes.h>
0049 
0050 #include <rtems/monitor.h>
0051 #include "symbols.h"
0052 
0053 
0054 rtems_symbol_table_t *
0055 rtems_symbol_table_create(void)
0056 {
0057     rtems_symbol_table_t *table;
0058 
0059     table = (rtems_symbol_table_t *) malloc(sizeof(rtems_symbol_table_t));
0060     memset((void *) table, 0, sizeof(*table));
0061 
0062     table->growth_factor = 30;          /* 30 percent */
0063 
0064     return table;
0065 }
0066 
0067 void
0068 rtems_symbol_table_destroy(rtems_symbol_table_t *table)
0069 {
0070     rtems_symbol_string_block_t *p, *pnext;
0071 
0072     if (table)
0073     {
0074         if (table->addresses)
0075             (void) free(table->addresses);
0076         table->addresses = 0;
0077         p = table->string_buffer_head;
0078         while (p)
0079         {
0080             pnext = p->next;
0081             free(p);
0082             p = pnext;
0083         }
0084         table->string_buffer_head = 0;
0085         table->string_buffer_current = 0;
0086 
0087         free(table);
0088     }
0089 }
0090 
0091 rtems_symbol_t *
0092 rtems_symbol_create(
0093     rtems_symbol_table_t *table,
0094     const char           *name,
0095     uint32_t              value
0096     )
0097 {
0098     size_t symbol_length;
0099     size_t newsize;
0100     rtems_symbol_t *sp;
0101 
0102     symbol_length = strlen(name) + 1;   /* include '\000' in length */
0103 
0104     /* need to grow the table? */
0105     if (table->next >= table->size)
0106     {
0107         if (table->size == 0)
0108             newsize = 100;
0109         else
0110             newsize = table->size + (table->size / (100 / table->growth_factor));
0111 
0112         table->addresses = (rtems_symbol_t *) realloc((void *) table->addresses, newsize * sizeof(rtems_symbol_t));
0113         if (table->addresses == 0)        /* blew it; lost orig */
0114             goto failed;
0115         table->size = newsize;
0116     }
0117 
0118     sp = &table->addresses[table->next];
0119     sp->value = value;
0120 
0121     /* Have to add it to string pool */
0122     /* need to grow pool? */
0123 
0124     if ((table->string_buffer_head == 0) ||
0125         (table->strings_next + symbol_length) >= SYMBOL_STRING_BLOCK_SIZE)
0126     {
0127         rtems_symbol_string_block_t *p;
0128 
0129         p = (rtems_symbol_string_block_t *) malloc(sizeof(rtems_symbol_string_block_t));
0130         if (p == 0)
0131             goto failed;
0132         p->next = 0;
0133         if (table->string_buffer_head == 0)
0134             table->string_buffer_head = p;
0135         else
0136             table->string_buffer_current->next = p;
0137         table->string_buffer_current = p;
0138 
0139         table->strings_next = 0;
0140     }
0141 
0142     sp->name = table->string_buffer_current->buffer + table->strings_next;
0143     (void) strcpy(sp->name, name);
0144 
0145     table->strings_next += symbol_length;
0146     table->sorted = 0;
0147     table->next++;
0148 
0149     return sp;
0150 
0151 /* XXX Not sure what to do here.  We've possibly destroyed the initial
0152    symbol table due to realloc failure */
0153 failed:
0154     return 0;
0155 }
0156 
0157 /*
0158  * Qsort entry point for compare by address
0159  */
0160 
0161 static int
0162 rtems_symbol_compare(const void *e1,
0163                      const void *e2)
0164 {
0165     const rtems_symbol_t *s1, *s2;
0166     s1 = (const rtems_symbol_t *) e1;
0167     s2 = (const rtems_symbol_t *) e2;
0168 
0169     if (s1->value < s2->value)
0170         return -1;
0171     if (s1->value > s2->value)
0172         return 1;
0173     return 0;
0174 }
0175 
0176 
0177 /*
0178  * Sort the symbol table using qsort
0179  */
0180 
0181 static void
0182 rtems_symbol_sort(rtems_symbol_table_t *table)
0183 {
0184     qsort((void *) table->addresses, (size_t) table->next,
0185           sizeof(rtems_symbol_t), rtems_symbol_compare);
0186     table->sorted = 1;
0187 }
0188 
0189 
0190 /*
0191  * Search the symbol table by address
0192  * This code based on CYGNUS newlib bsearch, but changed
0193  * to allow for finding closest symbol <= key
0194  */
0195 
0196 rtems_symbol_t *
0197 rtems_symbol_value_lookup(
0198     rtems_symbol_table_t *table,
0199     uint32_t              value
0200   )
0201 {
0202     rtems_symbol_t *sp;
0203     rtems_symbol_t *base;
0204     rtems_symbol_t *best = 0;
0205     uint32_t   distance;
0206     uint32_t   best_distance = ~0;
0207     uint32_t   elements;
0208 
0209     if (table == 0)
0210         table = rtems_monitor_symbols;
0211 
0212     if ((table == 0) || (table->size == 0))
0213         return 0;
0214 
0215     if (table->sorted == 0)
0216         rtems_symbol_sort(table);
0217 
0218     base = table->addresses;
0219     elements = table->next;
0220 
0221     while (elements)
0222     {
0223         sp = base + (elements / 2);
0224         if (value < sp->value)
0225             elements /= 2;
0226         else if (value > sp->value)
0227         {
0228             distance = value - sp->value;
0229             if (distance < best_distance)
0230             {
0231                 best_distance = distance;
0232                 best = sp;
0233             }
0234             base = sp + 1;
0235             elements = (elements / 2) - (elements % 2 ? 0 : 1);
0236         }
0237         else
0238             return sp;
0239     }
0240 
0241     if (value == base->value)
0242         return base;
0243 
0244     return best;
0245 }
0246 
0247 /*
0248  * Search the symbol table for the exact matching address.
0249  * If the symbol table has already been sorted, then
0250  * call the regular symbol value lookup, however, it it
0251  * has not yet been sorted, search it sequentially.
0252  * This routine is primarily used for low level symbol
0253  * lookups (eg. from exception handler and interrupt routines)
0254  * where the penality of sorted is not wanted and where
0255  * an exact match is needed such that symbol table order
0256  * is not important.
0257  */
0258 const rtems_symbol_t *
0259 rtems_symbol_value_lookup_exact(
0260     rtems_symbol_table_t *table,
0261     uint32_t              value
0262   )
0263 {
0264     uint32_t   s;
0265     rtems_symbol_t *sp;
0266 
0267     if (table == 0)
0268     {
0269         table = rtems_monitor_symbols;
0270         if (table == 0)
0271             return NULL;
0272     }
0273 
0274     if (table->sorted)
0275     {
0276         sp = rtems_symbol_value_lookup(table, value);
0277         if ( rtems_symbol_value(sp) == value )
0278             return sp;
0279         else
0280             return NULL;  /* not an exact match */
0281     }
0282 
0283     for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
0284     {
0285         if ( sp->value == value )
0286             return sp;
0287     }
0288 
0289     return NULL;
0290 
0291 }
0292 
0293 
0294 /*
0295  * Search the symbol table by string name (case independent)
0296  */
0297 
0298 rtems_symbol_t *
0299 rtems_symbol_name_lookup(
0300     rtems_symbol_table_t *table,
0301     const char           *name
0302   )
0303 {
0304     uint32_t   s;
0305     rtems_symbol_t *sp;
0306 
0307     if (table == 0)
0308     {
0309         table = rtems_monitor_symbols;
0310         if (table == 0)
0311             return NULL;
0312     }
0313 
0314     for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
0315     {
0316         if ( strcasecmp(sp->name, name) == 0 )
0317             return sp;
0318     }
0319 
0320     return NULL;
0321 }
0322 
0323 const void *
0324 rtems_monitor_symbol_next(
0325     void                   *object_info,
0326     rtems_monitor_symbol_t *canonical RTEMS_UNUSED,
0327     rtems_id               *next_id
0328 )
0329 {
0330     rtems_symbol_table_t *table;
0331     uint32_t   n = rtems_object_id_get_index(*next_id);
0332 
0333     table = *(rtems_symbol_table_t **) object_info;
0334     if (table == 0)
0335         goto failed;
0336 
0337     if (n >= table->next)
0338         goto failed;
0339 
0340     /* NOTE: symbols do not have id and name fields */
0341 
0342     if (table->sorted == 0)
0343         rtems_symbol_sort(table);
0344 
0345     _Objects_Allocator_lock();
0346 
0347     *next_id += 1;
0348     return (const void *) (table->addresses + n);
0349 
0350 failed:
0351     *next_id = RTEMS_OBJECT_ID_FINAL;
0352     return 0;
0353 }
0354 
0355 void
0356 rtems_monitor_symbol_canonical(
0357     rtems_monitor_symbol_t *canonical_symbol,
0358     rtems_symbol_t *sp
0359 )
0360 {
0361     canonical_symbol->value = sp->value;
0362     canonical_symbol->offset = 0;
0363     strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1);
0364 }
0365 
0366 
0367 void
0368 rtems_monitor_symbol_canonical_by_name(
0369     rtems_monitor_symbol_t *canonical_symbol,
0370     const char             *name
0371 )
0372 {
0373     rtems_symbol_t *sp;
0374 
0375     sp = rtems_symbol_name_lookup(0, name);
0376 
0377     canonical_symbol->value = sp ? sp->value : 0;
0378 
0379     strncpy(canonical_symbol->name, name, sizeof(canonical_symbol->name) - 1);
0380     canonical_symbol->offset = 0;
0381 }
0382 
0383 void
0384 rtems_monitor_symbol_canonical_by_value(
0385     rtems_monitor_symbol_t *canonical_symbol,
0386     void                   *value_void_p
0387 )
0388 {
0389     uintptr_t   value = (uintptr_t) value_void_p;
0390     rtems_symbol_t *sp;
0391 
0392     sp = rtems_symbol_value_lookup(0, value);
0393     if (sp)
0394     {
0395         canonical_symbol->value = sp->value;
0396         canonical_symbol->offset = value - sp->value;
0397         strncpy(canonical_symbol->name, sp->name, sizeof(canonical_symbol->name)-1);
0398     }
0399     else
0400     {
0401         canonical_symbol->value = value;
0402         canonical_symbol->offset = 0;
0403         canonical_symbol->name[0] = '\0';
0404     }
0405 }
0406 
0407 
0408 uint32_t
0409 rtems_monitor_symbol_dump(
0410     rtems_monitor_symbol_t *canonical_symbol,
0411     bool                    verbose
0412 )
0413 {
0414     uint32_t   length = 0;
0415 
0416     /*
0417      * print the name if it exists AND if value is non-zero
0418      * Ie: don't print some garbage symbol for address 0
0419      */
0420 
0421     if (canonical_symbol->name[0] && (canonical_symbol->value != 0))
0422     {
0423         if (canonical_symbol->offset == 0)
0424             length += fprintf(stdout,"%.*s",
0425                              (int) sizeof(canonical_symbol->name),
0426                              canonical_symbol->name);
0427         else
0428             length += fprintf(stdout,"<%.*s+0x%" PRIx32 ">",
0429                              (int) sizeof(canonical_symbol->name),
0430                              canonical_symbol->name,
0431                              canonical_symbol->offset);
0432         if (verbose)
0433             length += fprintf(stdout,
0434                         " [0x%" PRIx32 "]", canonical_symbol->value);
0435     }
0436     else
0437         length += fprintf(stdout,"[0x%" PRIx32 "]", canonical_symbol->value);
0438 
0439     return length;
0440 }
0441 
0442 
0443 static void
0444 rtems_monitor_symbol_dump_all(
0445     rtems_symbol_table_t *table,
0446     bool                  verbose RTEMS_UNUSED
0447 )
0448 {
0449     uint32_t   s;
0450     rtems_symbol_t *sp;
0451 
0452     if (table == 0)
0453     {
0454         table = rtems_monitor_symbols;
0455         if (table == 0)
0456             return;
0457     }
0458 
0459     if (table->sorted == 0)
0460         rtems_symbol_sort(table);
0461 
0462     for (s = 0, sp = table->addresses; s < table->next; s++, sp++)
0463     {
0464         rtems_monitor_symbol_t canonical_symbol;
0465 
0466         rtems_monitor_symbol_canonical(&canonical_symbol, sp);
0467         rtems_monitor_symbol_dump(&canonical_symbol, true);
0468         fprintf(stdout,"\n");
0469     }
0470 }
0471 
0472 
0473 /*
0474  * 'symbol' command
0475  */
0476 
0477 void rtems_monitor_symbol_cmd(
0478   int                                argc,
0479   char                             **argv,
0480   const rtems_monitor_command_arg_t *command_arg,
0481   bool                               verbose
0482 )
0483 {
0484     int arg;
0485     rtems_symbol_table_t *table;
0486 
0487     table = *command_arg->symbol_table;
0488     if (table == 0)
0489     {
0490         table = rtems_monitor_symbols;
0491         if (table == 0)
0492             return;
0493     }
0494 
0495     /*
0496      * Use object command to dump out whole symbol table
0497      */
0498     if (argc == 1)
0499         rtems_monitor_symbol_dump_all(table, verbose);
0500     else
0501     {
0502         rtems_monitor_symbol_t canonical_symbol;
0503 
0504         for (arg=1; argv[arg]; arg++)
0505         {
0506             rtems_monitor_symbol_canonical_by_name(&canonical_symbol, argv[arg]);
0507             rtems_monitor_symbol_dump(&canonical_symbol, verbose);
0508             fprintf(stdout,"\n");
0509         }
0510     }
0511 }