cpukit/libdl: Fix loading symbols from an object file at runtime

- Assume a relocation record with a symbol name with a length of
  0 is resolved. ARM seems to create a symbol with no name for
  R_ARM_V4BX relocation records.

- Move the addition of the rtems_rtl_base_sym_global_add symbol
  to the global symbol table to the weak
  rtems_rtl_base_global_syms_init call. If symbols are
  embedded the support for runtime loading symbols is over
  loaded. This change is required so the base object has a
  valid global symbol table attached to track dependencies.

Fixes #5234
This commit is contained in:
Chris Johns
2025-04-01 11:43:10 +11:00
parent 7205078179
commit e640d6b602
6 changed files with 64 additions and 26 deletions

View File

@@ -374,7 +374,7 @@ static inline size_t rtems_rtl_obj_align (size_t offset,
}
/**
* Is the symbol in this object's files globa symbol table?
* Is the symbol in this object's files global symbol table?
*
* @param obj The object file's descriptor to search.
* @param sym The symbol to check.

View File

@@ -97,6 +97,15 @@ bool rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
*/
void rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols);
/**
* Insert a symbol into a symbol table.
*
* @param symbols Symbol table
* @param symbols Symbol to add
*/
void rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol);
/**
* Add a table of exported symbols to the symbol table.
*

View File

@@ -557,6 +557,8 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
resolved = rtems_rtl_elf_find_symbol (obj,
&sym, symname,
&symbol, &symvalue);
if (symname != NULL && strlen(symname) == 0)
resolved = true;
if (!handler (obj,
is_rela, relbuf, targetsect,

View File

@@ -48,16 +48,6 @@
#include <rtems/rtl/rtl-sym.h>
#include <rtems/rtl/rtl-trace.h>
/**
* The single symbol forced into the global symbol table that is used to load a
* symbol table from an object file.
*/
static rtems_rtl_obj_sym global_sym_add =
{
.name = "rtems_rtl_base_sym_global_add",
.value = (void*) rtems_rtl_base_sym_global_add
};
static uint_fast32_t
rtems_rtl_symbol_hash (const char *s)
{
@@ -68,15 +58,6 @@ rtems_rtl_symbol_hash (const char *s)
return h & 0xffffffff;
}
static void
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol)
{
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
&symbol->node);
}
static const rtems_rtl_tls_offset*
rtems_rtl_symbol_find_tls_offset (size_t index,
const rtems_rtl_tls_offset* tls_offsets,
@@ -108,7 +89,6 @@ rtems_rtl_symbol_table_open (rtems_rtl_symbols* symbols,
symbols->nbuckets = buckets;
for (buckets = 0; buckets < symbols->nbuckets; ++buckets)
rtems_chain_initialize_empty (&symbols->buckets[buckets]);
rtems_rtl_symbol_global_insert (symbols, &global_sym_add);
return true;
}
@@ -118,6 +98,15 @@ rtems_rtl_symbol_table_close (rtems_rtl_symbols* symbols)
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, symbols->buckets);
}
void
rtems_rtl_symbol_global_insert (rtems_rtl_symbols* symbols,
rtems_rtl_obj_sym* symbol)
{
uint_fast32_t hash = rtems_rtl_symbol_hash (symbol->name);
rtems_chain_append (&symbols->buckets[hash % symbols->nbuckets],
&symbol->node);
}
bool
rtems_rtl_symbol_global_add (rtems_rtl_obj* obj,
const unsigned char* esyms,

View File

@@ -562,10 +562,18 @@ rtems_rtl_unresolved_add (rtems_rtl_obj* obj,
rtems_rtl_unresolv_block* block;
rtems_rtl_unresolv_rec* rec;
int name_index;
const int name_len = (int) strlen(name);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
rtems_rtl_obj_oname (obj), sect, name);
printf ("rtl: unresolv: add: %s(s:%d) -> '%s' (len: %i)\n",
rtems_rtl_obj_oname (obj), sect, name, name_len);
/*
* No name or an empty name is not able to resolved?
*/
if (name_len == 0) {
return false;
}
unresolved = rtems_rtl_unresolved_unprotected ();
if (!unresolved)

View File

@@ -78,17 +78,47 @@
static rtems_rtl_data* rtl;
static bool rtl_data_init;
/**
* The single symbol forced into the global symbol table that is used to load a
* symbol table from an object file.
*/
static rtems_rtl_obj_sym default_global_syms =
{
.name = "rtems_rtl_base_sym_global_add",
.value = (void*) rtems_rtl_base_sym_global_add
};
/**
* Define a default base global symbol loader function that is weak
* so a real table can be linked in when the user wants one.
*
* The default init handler add the one symbol used when loading
* symbols with an object file. It is an unresolved external in that
* object file.
*/
void rtems_rtl_base_global_syms_init (void) __attribute__ ((weak));
void
rtems_rtl_base_global_syms_init (void)
{
/*
* Do nothing.
*/
rtems_rtl_symbols* symbols;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_GLOBAL_SYM))
printf ("rtl: adding default global symbol\n");
if (!rtems_rtl_lock ())
{
rtems_rtl_set_error (EINVAL, "global add cannot lock rtl");
return;
}
symbols = rtems_rtl_global_symbols ();
rtl->base->global_table = &default_global_syms;
rtl->base->global_syms = 1;
rtems_rtl_symbol_global_insert (symbols, &default_global_syms);
rtems_rtl_unlock ();
}
static bool