File indexing completed on 2025-05-11 08:24:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 #ifdef HAVE_CONFIG_H
0037 #include "config.h"
0038 #endif
0039
0040 #include <errno.h>
0041 #include <inttypes.h>
0042 #include <stdlib.h>
0043 #include <stdio.h>
0044 #include <string.h>
0045
0046 #include <rtems/rtl/rtl.h>
0047 #include "rtl-error.h"
0048 #include <rtems/rtl/rtl-sym.h>
0049 #include <rtems/rtl/rtl-trace.h>
0050
0051
0052
0053
0054
0055 static rtems_rtl_obj_sym global_sym_add =
0056 {
0057 .name = "rtems_rtl_base_sym_global_add",
0058 .value = (void*) rtems_rtl_base_sym_global_add
0059 };
0060
0061 static uint_fast32_t
0062 rtems_rtl_symbol_hash (const char *s)
0063 {
0064 uint_fast32_t h = 5381;
0065 unsigned char c;
0066 for (c = *s; c != '\0'; c = *++s)
0067 h = h * 33 + c;
0068 return h & 0xffffffff;
0069 }
0070
0071 static void
0072 rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
0073 rtems_rtl_obj_sym* symbol)
0074 {
0075 uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
0076 rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
0077 &symbol->node);
0078 }
0079
0080 static const rtems_rtl_tls_offset*
0081 rtems_rtl_symbol_find_tls_offset (size_t index,
0082 const rtems_rtl_tls_offset* tls_offsets,
0083 size_t tls_size)
0084 {
0085 size_t entry;
0086 for (entry = 0; entry < tls_size; ++entry)
0087 {
0088 if (tls_offsets[entry].index == index)
0089 {
0090 return &tls_offsets[entry];
0091 }
0092 }
0093 return NULL;
0094 }
0095
0096 bool
0097 rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
0098 size_t buckets)
0099 {
0100 symbols->buckets = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
0101 buckets * sizeof (rtems_chain_control),
0102 true);
0103 if (!symbols->buckets)
0104 {
0105 rtems_rtl_set_error (ENOMEM, "no memory for global symbol table");
0106 return false;
0107 }
0108 symbols->nbuckets = buckets;
0109 for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
0110 rtems_chain_initialize_empty (&symbols->buckets[buckets]);
0111 rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
0112 return true;
0113 }
0114
0115 void
0116 rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
0117 {
0118 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
0119 }
0120
0121 bool
0122 rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
0123 const unsigned char* esyms,
0124 unsigned int size,
0125 const rtems_rtl_tls_offset* tls_offsets,
0126 unsigned int tls_size)
0127 {
0128 rtems_rtl_symbols* symbols;
0129 rtems_rtl_obj_sym* sym;
0130 size_t count;
0131 size_t s;
0132 uint32_t marker;
0133
0134 count = 0;
0135 s = 0;
0136 while ((s < size) && (esyms[s] != 0))
0137 {
0138 int l = strlen ((char*) &esyms[s]);
0139 if ((esyms[s + l] != '\0') || ((s + l) > size))
0140 {
0141 rtems_rtl_set_error (EINVAL, "invalid exported symbol table");
0142 return false;
0143 }
0144 ++count;
0145 s += l + sizeof (void *) + 1;
0146 }
0147
0148
0149
0150
0151 marker = esyms[s + 1];
0152 marker <<= 8;
0153 marker |= esyms[s + 2];
0154 marker <<= 8;
0155 marker |= esyms[s + 3];
0156 marker <<= 8;
0157 marker |= esyms[s + 4];
0158
0159 if (marker != 0xdeadbeefUL)
0160 {
0161 rtems_rtl_set_error (ENOMEM, "invalid export symbol table");
0162 return false;
0163 }
0164
0165 if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
0166 printf ("rtl: global symbol add: %zi\n", count);
0167
0168 obj->global_size = count * sizeof (rtems_rtl_obj_sym);
0169 obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL,
0170 obj->global_size, true);
0171 if (!obj->global_table)
0172 {
0173 obj->global_size = 0;
0174 rtems_rtl_set_error (ENOMEM, "no memory for global symbols");
0175 return false;
0176 }
0177
0178 symbols = rtems_rtl_global_symbols ();
0179
0180 obj->global_syms = count;
0181
0182 count = 0;
0183 s = 0;
0184 sym = obj->global_table;
0185
0186 while ((s < size) && (esyms[s] != 0))
0187 {
0188
0189
0190
0191
0192
0193 union {
0194 uint8_t data[sizeof (void*)];
0195 void* voidp;
0196 } copy_voidp;
0197 const rtems_rtl_tls_offset* tls_off;
0198 int b;
0199
0200 sym->name = (const char*) &esyms[s];
0201 s += strlen (sym->name) + 1;
0202 for (b = 0; b < sizeof (void*); ++b, ++s)
0203 copy_voidp.data[b] = esyms[s];
0204 tls_off = rtems_rtl_symbol_find_tls_offset (count, tls_offsets, tls_size);
0205 if (tls_off == NULL) {
0206 sym->value = copy_voidp.voidp;
0207 } else {
0208 sym->value = (void*) tls_off->offset();
0209 }
0210 if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
0211 printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value);
0212 if (rtems_rtl_symbol_global_find (sym->name) == NULL)
0213 rtems_rtl_symbol_global_insert (symbols, sym);
0214 ++count;
0215 ++sym;
0216 }
0217
0218 return true;
0219 }
0220
0221 rtems_rtl_obj_sym*
0222 rtems_rtl_symbol_global_find (const char* name)
0223 {
0224 rtems_rtl_symbols* symbols;
0225 uint_fast32_t hash;
0226 rtems_chain_control* bucket;
0227 rtems_chain_node* node;
0228
0229 symbols = rtems_rtl_global_symbols ();
0230
0231 hash = rtems_rtl_symbol_hash (name);
0232 bucket = &symbols->buckets[hash % symbols->nbuckets];
0233 node = rtems_chain_first (bucket);
0234
0235 while (!rtems_chain_is_tail (bucket, node))
0236 {
0237 rtems_rtl_obj_sym* sym = (rtems_rtl_obj_sym*) node;
0238
0239
0240
0241 if (strcmp (name, sym->name) == 0)
0242 return sym;
0243 node = rtems_chain_next (node);
0244 }
0245
0246 return NULL;
0247 }
0248
0249 static int
0250 rtems_rtl_symbol_obj_compare (const void* a, const void* b)
0251 {
0252 const rtems_rtl_obj_sym* sa;
0253 const rtems_rtl_obj_sym* sb;
0254 sa = (const rtems_rtl_obj_sym*) a;
0255 sb = (const rtems_rtl_obj_sym*) b;
0256 return strcmp (sa->name, sb->name);
0257 }
0258
0259 void
0260 rtems_rtl_symbol_obj_sort (rtems_rtl_obj* obj)
0261 {
0262 qsort (obj->local_table,
0263 obj->local_syms,
0264 sizeof (rtems_rtl_obj_sym),
0265 rtems_rtl_symbol_obj_compare);
0266 qsort (obj->global_table,
0267 obj->global_syms,
0268 sizeof (rtems_rtl_obj_sym),
0269 rtems_rtl_symbol_obj_compare);
0270 }
0271
0272 rtems_rtl_obj_sym*
0273 rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj, const char* name)
0274 {
0275
0276
0277
0278
0279 if (obj->local_syms)
0280 {
0281 rtems_rtl_obj_sym* match;
0282 rtems_rtl_obj_sym key = { 0 };
0283 key.name = name;
0284 match = bsearch (&key, obj->local_table,
0285 obj->local_syms,
0286 sizeof (rtems_rtl_obj_sym),
0287 rtems_rtl_symbol_obj_compare);
0288 if (match != NULL)
0289 return match;
0290 }
0291 if (obj->global_syms)
0292 {
0293 rtems_rtl_obj_sym* match;
0294 rtems_rtl_obj_sym key = { 0 };
0295 key.name = name;
0296 match = bsearch (&key, obj->global_table,
0297 obj->global_syms,
0298 sizeof (rtems_rtl_obj_sym),
0299 rtems_rtl_symbol_obj_compare);
0300 if (match != NULL)
0301 return match;
0302 }
0303 return rtems_rtl_symbol_global_find (name);
0304 }
0305
0306 void
0307 rtems_rtl_symbol_obj_add (rtems_rtl_obj* obj)
0308 {
0309 rtems_rtl_symbols* symbols;
0310 rtems_rtl_obj_sym* sym;
0311 size_t s;
0312
0313 symbols = rtems_rtl_global_symbols ();
0314
0315 for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
0316 rtems_rtl_symbol_global_insert (symbols, sym);
0317 }
0318
0319 void
0320 rtems_rtl_symbol_obj_erase_local (rtems_rtl_obj* obj)
0321 {
0322 if (obj->local_table)
0323 {
0324 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
0325 obj->local_table = NULL;
0326 obj->local_size = 0;
0327 obj->local_syms = 0;
0328 }
0329 }
0330
0331 void
0332 rtems_rtl_symbol_obj_erase (rtems_rtl_obj* obj)
0333 {
0334 rtems_rtl_symbol_obj_erase_local (obj);
0335 if (obj->global_table)
0336 {
0337 rtems_rtl_obj_sym* sym;
0338 size_t s;
0339 for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym)
0340 if (!rtems_chain_is_node_off_chain (&sym->node))
0341 rtems_chain_extract (&sym->node);
0342 rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
0343 obj->global_table = NULL;
0344 obj->global_size = 0;
0345 obj->global_syms = 0;
0346 }
0347 }