static bool rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec_t* rec, void* data) { if (rec->type == rtems_rtl_unresolved_name) { rtems_rtl_unresolved_reloc_data_t* rd; rd = (rtems_rtl_unresolved_reloc_data_t*) data; ++rd->name; if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED)) printf ("rtl: unresolv: lookup: %d: %s\n", rd->name, rec->rec.name.name); rd->sym = rtems_rtl_symbol_global_find (rec->rec.name.name); if (rd->sym) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED)) printf ("rtl: unresolv: found: %s\n", rec->rec.name.name); rd->name_rec = rec; rtems_rtl_unresolved_interate (rtems_rtl_unresolved_resolve_reloc, rd); rd->name_rec = NULL; rd->sym = NULL; } } return false; }
rtems_rtl_obj_sym_t* rtems_rtl_symbol_obj_find (rtems_rtl_obj_t* obj, const char* name) { rtems_rtl_obj_sym_t* sym; size_t s; /* * Check the object file's symbols first. If not found search the * global symbol table. */ if (obj->local_syms) { for (s = 0, sym = obj->local_table; s < obj->local_syms; ++s, ++sym) if (strcmp (name, sym->name) == 0) return sym; } if (obj->global_syms) { for (s = 0, sym = obj->global_table; s < obj->global_syms; ++s, ++sym) if (strcmp (name, sym->name) == 0) return sym; } return rtems_rtl_symbol_global_find (name); }
bool rtems_rtl_symbol_global_add (rtems_rtl_obj_t* obj, const unsigned char* esyms, unsigned int size) { rtems_rtl_symbols_t* symbols; rtems_rtl_obj_sym_t* sym; size_t count; size_t s; uint32_t marker; count = 0; s = 0; while ((s < size) && (esyms[s] != 0)) { int l = strlen ((char*) &esyms[s]); if ((esyms[s + l] != '\0') || ((s + l) > size)) { rtems_rtl_set_error (EINVAL, "invalid exported symbol table"); return false; } ++count; s += l + sizeof (unsigned long) + 1; } /* * Check this is the correct end of the table. */ marker = esyms[s + 1]; marker <<= 8; marker |= esyms[s + 2]; marker <<= 8; marker |= esyms[s + 3]; marker <<= 8; marker |= esyms[s + 4]; if (marker != 0xdeadbeefUL) { rtems_rtl_set_error (ENOMEM, "invalid export symbol table"); return false; } if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: global symbol add: %zi\n", count); obj->global_size = count * sizeof (rtems_rtl_obj_sym_t); obj->global_table = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_SYMBOL, obj->global_size, true); if (!obj->global_table) { obj->global_size = 0; rtems_rtl_set_error (ENOMEM, "no memory for global symbols"); return false; } symbols = rtems_rtl_global_symbols (); s = 0; sym = obj->global_table; while ((s < size) && (esyms[s] != 0)) { /* * Copy the void* using a union and memcpy to avoid any strict aliasing or * alignment issues. The variable length of the label and the packed nature * of the table means casting is not suitable. */ union { uint8_t data[sizeof (void*)]; void* value; } copy_voidp; int b; sym->name = (const char*) &esyms[s]; s += strlen (sym->name) + 1; for (b = 0; b < sizeof (void*); ++b, ++s) copy_voidp.data[b] = esyms[s]; sym->value = copy_voidp.value; if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM)) printf ("rtl: esyms: %s -> %8p\n", sym->name, sym->value); if (rtems_rtl_symbol_global_find (sym->name) == NULL) rtems_rtl_symbol_global_insert (symbols, sym); ++sym; } obj->global_syms = count; return true; }