forked from Imagelibrary/rtems
libdl: Add support for large memory programs
- Add trampolines to support relocs that are out of range on support architectures. - Support not loading separate text/data sections in an object file if the symbol provided in the section is a duplicate. A base image may have pulled in part of an object and another part needs to be dynamically loaded. - Refactor the unresolved handling to scale to hundreds of unresolved symbols when loading large number of files. Updates #3685
This commit is contained in:
@@ -92,19 +92,20 @@ typedef struct rtems_rtl_loader_table
|
||||
#define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */
|
||||
#define RTEMS_RTL_OBJ_SECT_EH (1 << 4) /**< Section holds exception data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_REL (1 << 5) /**< Section holds relocation recs. */
|
||||
#define RTEMS_RTL_OBJ_SECT_RELA (1 << 6) /**< Section holds reloc addend recs. */
|
||||
#define RTEMS_RTL_OBJ_SECT_SYM (1 << 7) /**< Section holds symbols. */
|
||||
#define RTEMS_RTL_OBJ_SECT_STR (1 << 8) /**< Section holds strings. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 9) /**< Section allocates runtime memory. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 10) /**< Section is loaded from object file. */
|
||||
#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 11) /**< Section is writable, ie data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 12) /**< Section is executable. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 13) /**< Section is preset to zero. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LINK (1 << 14) /**< Section is link-ordered. */
|
||||
#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 15) /**< Section contains constructors. */
|
||||
#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 16) /**< Section contains destructors. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LOCD (1 << 17) /**< Section has been located. */
|
||||
#define RTEMS_RTL_OBJ_SECT_TLS (1 << 5) /**< Section holds TLS data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_REL (1 << 6) /**< Section holds relocation recs. */
|
||||
#define RTEMS_RTL_OBJ_SECT_RELA (1 << 7) /**< Section holds reloc addend recs. */
|
||||
#define RTEMS_RTL_OBJ_SECT_SYM (1 << 8) /**< Section holds symbols. */
|
||||
#define RTEMS_RTL_OBJ_SECT_STR (1 << 9) /**< Section holds strings. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 10 /**< Section allocates runtime memory. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 11) /**< Section is loaded from object file. */
|
||||
#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 12) /**< Section is writable, ie data. */
|
||||
#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 13) /**< Section is executable. */
|
||||
#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 14) /**< Section is preset to zero. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LINK (1 << 15) /**< Section is link-ordered. */
|
||||
#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 16) /**< Section contains constructors. */
|
||||
#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 17) /**< Section contains destructors. */
|
||||
#define RTEMS_RTL_OBJ_SECT_LOCD (1 << 18) /**< Section has been located. */
|
||||
|
||||
/**
|
||||
* Section types mask.
|
||||
@@ -113,6 +114,7 @@ typedef struct rtems_rtl_loader_table
|
||||
RTEMS_RTL_OBJ_SECT_CONST | \
|
||||
RTEMS_RTL_OBJ_SECT_DATA | \
|
||||
RTEMS_RTL_OBJ_SECT_BSS | \
|
||||
RTEMS_RTL_OBJ_SECT_TLS | \
|
||||
RTEMS_RTL_OBJ_SECT_EH)
|
||||
|
||||
/**
|
||||
@@ -204,11 +206,13 @@ struct rtems_rtl_obj
|
||||
size_t text_size; /**< The size of the text section. */
|
||||
void* const_base; /**< The base address of the const section
|
||||
* in memory. */
|
||||
size_t const_size; /**< The size of the const section. */
|
||||
void* eh_base; /**< The base address of the eh section in
|
||||
* memory. */
|
||||
size_t eh_size; /**< The size of the eh section. */
|
||||
void* data_base; /**< The base address of the data section
|
||||
* in memory. */
|
||||
size_t data_size; /**< The size of the data section. */
|
||||
void* bss_base; /**< The base address of the bss section in
|
||||
* memory. */
|
||||
size_t bss_size; /**< The size of the bss section. */
|
||||
|
||||
@@ -49,8 +49,11 @@ typedef uint32_t rtems_rtl_trace_mask;
|
||||
#define RTEMS_RTL_TRACE_UNRESOLVED (1UL << 10)
|
||||
#define RTEMS_RTL_TRACE_CACHE (1UL << 11)
|
||||
#define RTEMS_RTL_TRACE_ARCHIVES (1UL << 12)
|
||||
#define RTEMS_RTL_TRACE_DEPENDENCY (1UL << 13)
|
||||
#define RTEMS_RTL_TRACE_ALL (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE))
|
||||
#define RTEMS_RTL_TRACE_ARCHIVE_SYMS (1UL << 13)
|
||||
#define RTEMS_RTL_TRACE_DEPENDENCY (1UL << 14)
|
||||
#define RTEMS_RTL_TRACE_ALL (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE | \
|
||||
RTEMS_RTL_TRACE_GLOBAL_SYM | \
|
||||
RTEMS_RTL_TRACE_ARCHIVE_SYMS))
|
||||
|
||||
/**
|
||||
* Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
#define _RTEMS_RTL_UNRESOLVED_H_
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/chain.h>
|
||||
#include "rtl-obj-fwd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -79,6 +80,8 @@ typedef enum rtems_rtl_unresolved_rtype
|
||||
* Unresolved external symbol flags.
|
||||
*/
|
||||
#define RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE (1 << 0) /**< Search the archive. */
|
||||
#define RTEMS_RTL_UNRESOLV_SYM_HAS_ERROR (1 << 1) /**< The symbol load
|
||||
* has an error. */
|
||||
|
||||
/**
|
||||
* Unresolved externals symbols. The symbols are reference counted and separate
|
||||
@@ -93,7 +96,7 @@ typedef struct rtems_rtl_unresolv_symbol
|
||||
uint16_t refs; /**< The number of references to this name. */
|
||||
uint16_t flags; /**< Flags to manage the symbol. */
|
||||
uint16_t length; /**< The length of this name. */
|
||||
const char name[10]; /**< The symbol name. */
|
||||
const char name[]; /**< The symbol name. */
|
||||
} rtems_rtl_unresolv_symbol;
|
||||
|
||||
/**
|
||||
@@ -117,7 +120,7 @@ typedef struct rtems_rtl_unresolv_rec
|
||||
rtems_rtl_unresolved_rtype type;
|
||||
union
|
||||
{
|
||||
rtems_rtl_unresolv_symbol name; /**< The symnbol, or */
|
||||
rtems_rtl_unresolv_symbol name; /**< The symbol, or */
|
||||
rtems_rtl_unresolv_reloc reloc; /**< the relocation record. */
|
||||
} rec;
|
||||
} rtems_rtl_unresolv_rec;
|
||||
@@ -129,7 +132,7 @@ typedef struct rtems_rtl_unresolv_block
|
||||
{
|
||||
rtems_chain_node link; /**< Blocks are chained. */
|
||||
uint32_t recs; /**< The number of records in the block. */
|
||||
rtems_rtl_unresolv_rec rec; /**< The records. More follow. */
|
||||
rtems_rtl_unresolv_rec rec[]; /**< The records. More follow. */
|
||||
} rtems_rtl_unresolv_block;
|
||||
|
||||
/**
|
||||
|
||||
@@ -137,6 +137,15 @@ rtems_rtl_data* rtems_rtl_data_unprotected (void);
|
||||
*/
|
||||
rtems_rtl_symbols* rtems_rtl_global_symbols (void);
|
||||
|
||||
/**
|
||||
* Get the RTL last error string with out locking. This call assumes the RTL is
|
||||
* locked.
|
||||
*
|
||||
* @return const char* The RTL's laste error.
|
||||
* @retval NULL The RTL data is not initialised.
|
||||
*/
|
||||
const char* rtems_rtl_last_error_unprotected (void);
|
||||
|
||||
/**
|
||||
* Get the RTL objects table with out locking. This call assumes the RTL
|
||||
* is locked.
|
||||
|
||||
@@ -293,33 +293,23 @@ rtems_rtl_archive_obj_finder (rtems_rtl_archive* archive, void* data)
|
||||
}
|
||||
else
|
||||
{
|
||||
ssize_t entry = symbols->entries / 2;
|
||||
ssize_t offset = entry;
|
||||
ssize_t last_entry = -1;
|
||||
while (entry >= 0 &&
|
||||
entry < symbols->entries &&
|
||||
entry != last_entry &&
|
||||
offset > 0)
|
||||
rtems_rtl_archive_symbol* match;
|
||||
const rtems_rtl_archive_symbol key = {
|
||||
.entry = -1,
|
||||
.label = search->symbol
|
||||
};
|
||||
match = bsearch (&key,
|
||||
symbols->symbols,
|
||||
symbols->entries,
|
||||
sizeof (symbols->symbols[0]),
|
||||
rtems_rtl_archive_symbol_compare);
|
||||
if (match != NULL)
|
||||
{
|
||||
int cmp = strcmp (search->symbol, symbols->symbols[entry].label);
|
||||
if (cmp == 0)
|
||||
{
|
||||
entry = symbols->symbols[entry].entry;
|
||||
search->archive = archive;
|
||||
search->offset =
|
||||
rtems_rtl_archive_read_32 (symbols->base + (entry * 4));
|
||||
rtems_rtl_archive_read_32 (symbols->base + (match->entry * 4));
|
||||
return false;
|
||||
}
|
||||
last_entry = entry;
|
||||
if (offset == 1)
|
||||
offset = 0;
|
||||
else
|
||||
offset = ((offset - 1) / 2) + 1;
|
||||
if (cmp < 0)
|
||||
entry -= offset;
|
||||
else
|
||||
entry += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -452,7 +442,7 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
|
||||
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
|
||||
archives->config_length = 0;
|
||||
archives->config =
|
||||
rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sb.st_size, false);
|
||||
rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sb.st_size + 1, true);
|
||||
if (archives->config == NULL)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
|
||||
@@ -519,45 +509,29 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
|
||||
* Remove leading and trailing white space.
|
||||
*/
|
||||
s = (char*) archives->config;
|
||||
for (r = 0; r < archives->config_length; ++r)
|
||||
r = 0;
|
||||
while (r < archives->config_length)
|
||||
{
|
||||
if (s[r] != '\0')
|
||||
if (s[r] == '\0')
|
||||
{
|
||||
++r;
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t ls = strlen (&s[r]);
|
||||
size_t b = 0;
|
||||
while (b < ls && isspace (s[r + b]))
|
||||
{
|
||||
s[r + b] = '\0';
|
||||
++b;
|
||||
}
|
||||
if (b > 0)
|
||||
memmove (&s[r], &s[r + b], ls - b);
|
||||
b = ls - 1;
|
||||
while (b > 0 && isspace (s[r + b]))
|
||||
while (b > 0 && isspace (s[b]))
|
||||
{
|
||||
s[r + b] = '\0';
|
||||
s[b] = '\0';
|
||||
--b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compact the lines so there is only a single nul separator.
|
||||
*/
|
||||
s = (char*) archives->config;
|
||||
for (r = 0; r < archives->config_length; ++r)
|
||||
{
|
||||
if (s[r] == '\0')
|
||||
{
|
||||
size_t e = r + 1;
|
||||
while (e < archives->config_length)
|
||||
{
|
||||
if (s[e] != '\0')
|
||||
{
|
||||
if (archives->config_length - e - 1 > 0)
|
||||
memmove (&s[r + 1], &s[e], archives->config_length - e - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
r += ls;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -565,13 +539,17 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
|
||||
{
|
||||
int line = 1;
|
||||
printf ("rtl: archive: config:\n");
|
||||
s = (char*) archives->config;
|
||||
for (r = 0; r < archives->config_length; ++r, ++line)
|
||||
r = 0;
|
||||
while (r < archives->config_length)
|
||||
{
|
||||
size_t len = strlen (s);
|
||||
printf (" %3d: %s\n", line, s);
|
||||
s += len + 2;
|
||||
r += len;
|
||||
const char* cs = &archives->config[r];
|
||||
size_t len = strlen (cs);
|
||||
if (len > 0)
|
||||
{
|
||||
printf (" %3d: %s\n", line, cs);
|
||||
++line;
|
||||
}
|
||||
r += len + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -740,6 +718,19 @@ rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
|
||||
archive->symbols.names,
|
||||
(archive->symbols.entries + 1) * 4,
|
||||
archive->symbols.symbols);
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVE_SYMS) &&
|
||||
archive->symbols.entries > 0)
|
||||
{
|
||||
size_t e;
|
||||
printf ("rtl: archive: symbols: %s\n", archive->name );
|
||||
for (e = 0; e < archive->symbols.entries; ++e)
|
||||
{
|
||||
printf(" %6zu: %6zu %s\n", e + 1,
|
||||
archive->symbols.symbols[e].entry,
|
||||
archive->symbols.symbols[e].label);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close (fd);
|
||||
@@ -851,12 +842,10 @@ rtems_rtl_archives_refresh (rtems_rtl_archives* archives)
|
||||
break;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
|
||||
printf ("rtl: archive: refresh: checking: %s\n", entry.d_name);
|
||||
printf ("rtl: archive: refresh: checking: %s (pattern: %s)\n",
|
||||
entry.d_name, basename);
|
||||
|
||||
if (fnmatch (basename, entry.d_name, 0) == 0)
|
||||
{
|
||||
struct stat sb;
|
||||
if (stat (entry.d_name, &sb) == 0)
|
||||
{
|
||||
rtems_rtl_archive* archive;
|
||||
archive = rtems_rtl_archive_get (archives, dirname, entry.d_name);
|
||||
@@ -865,7 +854,6 @@ rtems_rtl_archives_refresh (rtems_rtl_archives* archives)
|
||||
entry.d_name, archive == NULL ? ": not " : "");
|
||||
}
|
||||
}
|
||||
}
|
||||
closedir (dir);
|
||||
}
|
||||
|
||||
@@ -1028,8 +1016,9 @@ rtems_rtl_archive_obj_load (rtems_rtl_archives* archives,
|
||||
if (!rtems_rtl_obj_load (obj))
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
|
||||
printf ("rtl: archive: loading: error: %s:%s@0x%08jx\n",
|
||||
obj->aname, obj->oname, obj->ooffset);
|
||||
printf ("rtl: archive: loading: error: %s:%s@0x%08jx: %s\n",
|
||||
obj->aname, obj->oname, obj->ooffset,
|
||||
rtems_rtl_last_error_unprotected ());
|
||||
rtems_chain_extract (&obj->link);
|
||||
rtems_rtl_obj_free (obj);
|
||||
rtems_rtl_obj_caches_flush ();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
@@ -64,6 +65,31 @@ rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
|
||||
return true;
|
||||
}
|
||||
|
||||
static const char*
|
||||
rtems_rtl_elf_separated_section (const char* name)
|
||||
{
|
||||
struct {
|
||||
const char* label;
|
||||
size_t len;
|
||||
} prefix[] = {
|
||||
#define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 }
|
||||
SEPARATED_PREFIX (".text."),
|
||||
SEPARATED_PREFIX (".rel.text."),
|
||||
SEPARATED_PREFIX (".data."),
|
||||
SEPARATED_PREFIX (".rel.data."),
|
||||
SEPARATED_PREFIX (".rodata."),
|
||||
SEPARATED_PREFIX (".rel.rodata.")
|
||||
};
|
||||
const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]);
|
||||
size_t p;
|
||||
for (p = 0; p < prefixes; ++p)
|
||||
{
|
||||
if (strncmp (name, prefix[p].label, prefix[p].len) == 0)
|
||||
return name + prefix[p].len;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
|
||||
const Elf_Sym* sym,
|
||||
@@ -100,6 +126,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
|
||||
return false;
|
||||
|
||||
*value = sym->st_value + (Elf_Addr) sect->base;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -140,6 +167,18 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
|
||||
{
|
||||
rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
|
||||
|
||||
/*
|
||||
* The symbol has to have been resolved to parse the reloc record. Unresolved
|
||||
* symbols are handled in the relocator but we need to count them here so a
|
||||
* trampoline is accounted for. We have to assume the unresolved may be out of
|
||||
* of range.
|
||||
*/
|
||||
if (!resolved)
|
||||
{
|
||||
++rd->unresolved;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Check the reloc record to see if a trampoline is needed.
|
||||
*/
|
||||
@@ -168,15 +207,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the symbol has been resolved and there is a symbol name it is a global
|
||||
* symbol and from another object file so add it as a dependency.
|
||||
*/
|
||||
if (!resolved)
|
||||
{
|
||||
++rd->unresolved;
|
||||
}
|
||||
else if (symname != NULL)
|
||||
if (symname != NULL)
|
||||
{
|
||||
/*
|
||||
* Find the symbol's object file. It cannot be NULL so ignore that result
|
||||
@@ -197,6 +228,8 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,6 +346,14 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
|
||||
if (!targetsect)
|
||||
return true;
|
||||
|
||||
/*
|
||||
* The section muct has been loaded. It could be a separate section in an
|
||||
* archive and not loaded.
|
||||
*/
|
||||
if ((targetsect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == 0)
|
||||
return true;
|
||||
|
||||
|
||||
rtems_rtl_obj_caches (&symbols, &strings, &relocs);
|
||||
|
||||
if (!symbols || !strings || !relocs)
|
||||
@@ -379,6 +420,7 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
|
||||
* Only need the name of the symbol if global or a common symbol.
|
||||
*/
|
||||
if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
|
||||
ELF_ST_TYPE (sym.st_info) == STT_TLS ||
|
||||
sym.st_shndx == SHN_COMMON)
|
||||
{
|
||||
size_t len;
|
||||
@@ -686,6 +728,12 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
|
||||
symbol.st_shndx,
|
||||
(int) symbol.st_size);
|
||||
|
||||
/*
|
||||
* If a duplicate forget it.
|
||||
*/
|
||||
if (rtems_rtl_symbol_global_find (name))
|
||||
continue;
|
||||
|
||||
if ((symbol.st_shndx != 0) &&
|
||||
((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
|
||||
(ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
|
||||
@@ -705,17 +753,25 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
|
||||
{
|
||||
/*
|
||||
* If there is a globally exported symbol already present and this
|
||||
* symbol is not weak raise an error. If the symbol is weak and
|
||||
* present globally ignore this symbol and use the global one and if
|
||||
* it is not present take this symbol global or weak. We accept the
|
||||
* first weak symbol we find and make it globally exported.
|
||||
* symbol is not weak raise check if the object file being loaded is
|
||||
* from an archive. If the base image is built with text sections a
|
||||
* symbol with it's section will be linked into the base image and not
|
||||
* another symbol. If not an archive rause an error.
|
||||
*
|
||||
* If the symbol is weak and present globally ignore this symbol and
|
||||
* use the global one and if it is not present take this symbol global
|
||||
* or weak. We accept the first weak symbol we find and make it
|
||||
* globally exported.
|
||||
*/
|
||||
if (rtems_rtl_symbol_global_find (name) &&
|
||||
(ELF_ST_BIND (symbol.st_info) != STB_WEAK))
|
||||
{
|
||||
if (!rtems_rtl_obj_aname_valid (obj))
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
|
||||
@@ -786,7 +842,6 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
|
||||
{
|
||||
Elf_Sym symbol;
|
||||
off_t off;
|
||||
const char* name;
|
||||
size_t len;
|
||||
|
||||
off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
|
||||
@@ -811,12 +866,6 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
|
||||
return false;
|
||||
}
|
||||
|
||||
off = obj->ooffset + strtab->offset + symbol.st_name;
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
|
||||
return false;
|
||||
|
||||
if ((symbol.st_shndx != 0) &&
|
||||
((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
|
||||
(ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
|
||||
@@ -834,6 +883,20 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
|
||||
symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
|
||||
if (symsect)
|
||||
{
|
||||
const char* name;
|
||||
|
||||
off = obj->ooffset + strtab->offset + symbol.st_name;
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* If a duplicate forget it.
|
||||
*/
|
||||
if (rtems_rtl_symbol_global_find (name))
|
||||
continue;
|
||||
|
||||
if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
|
||||
(ELF_ST_BIND (symbol.st_info) == STB_WEAK))
|
||||
{
|
||||
@@ -955,6 +1018,8 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
|
||||
for (section = 0; section < ehdr->e_shnum; ++section)
|
||||
{
|
||||
char* name;
|
||||
size_t len;
|
||||
uint32_t flags;
|
||||
|
||||
/*
|
||||
@@ -968,9 +1033,15 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
|
||||
return false;
|
||||
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd,
|
||||
sectstroff + shdr.sh_name,
|
||||
(void**) &name, &len))
|
||||
return false;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
|
||||
printf ("rtl: section: %2d: type=%d flags=%08x link=%d info=%d\n",
|
||||
section, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
|
||||
printf ("rtl: section: %2d: name=%s type=%d flags=%08x link=%d info=%d\n",
|
||||
section, name, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
|
||||
(int) shdr.sh_link, (int) shdr.sh_info);
|
||||
|
||||
flags = 0;
|
||||
@@ -1010,7 +1081,7 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
break;
|
||||
|
||||
case SHT_RELA:
|
||||
flags = RTEMS_RTL_OBJ_SECT_RELA;
|
||||
flags = RTEMS_RTL_OBJ_SECT_RELA | RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
break;
|
||||
|
||||
case SHT_REL:
|
||||
@@ -1018,7 +1089,7 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
* The sh_link holds the section index for the symbol table. The sh_info
|
||||
* holds the section index the relocations apply to.
|
||||
*/
|
||||
flags = RTEMS_RTL_OBJ_SECT_REL;
|
||||
flags = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
break;
|
||||
|
||||
case SHT_SYMTAB:
|
||||
@@ -1063,8 +1134,18 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
|
||||
if (flags != 0)
|
||||
{
|
||||
char* name;
|
||||
size_t len;
|
||||
/*
|
||||
* If the object file is part of a library check the section's name. If it
|
||||
* starts with '.text.*' see if the last part is a global symbol. If a
|
||||
* global symbol exists we have to assume the symbol in the archive is a
|
||||
* duplicate can can be ignored.
|
||||
*/
|
||||
if (rtems_rtl_obj_aname_valid (obj))
|
||||
{
|
||||
const char* symname = rtems_rtl_elf_separated_section (name);
|
||||
if (symname != NULL && rtems_rtl_symbol_global_find (symname))
|
||||
flags &= ~RTEMS_RTL_OBJ_SECT_LOAD;
|
||||
}
|
||||
|
||||
/*
|
||||
* If link ordering this section must appear in the same order in memory
|
||||
@@ -1074,14 +1155,8 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
|
||||
flags |= RTEMS_RTL_OBJ_SECT_LINK;
|
||||
|
||||
/*
|
||||
* Some architexctures support a named PROGBIT section for INIT/FINI.
|
||||
* Some architexctures have a named PROGBIT section for INIT/FINI.
|
||||
*/
|
||||
len = RTEMS_RTL_ELF_STRING_MAX;
|
||||
if (!rtems_rtl_obj_cache_read (strings, fd,
|
||||
sectstroff + shdr.sh_name,
|
||||
(void**) &name, &len))
|
||||
return false;
|
||||
|
||||
if (strcmp (".ctors", name) == 0)
|
||||
flags |= RTEMS_RTL_OBJ_SECT_CTOR;
|
||||
if (strcmp (".dtors", name) == 0)
|
||||
@@ -1153,25 +1228,34 @@ rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
|
||||
{
|
||||
rtems_chain_control* sections = NULL;
|
||||
rtems_chain_node* node = NULL;
|
||||
size_t mask = 0;
|
||||
int sec_num = 0;
|
||||
section_detail* sd;
|
||||
int i = 0;
|
||||
size_t m;
|
||||
|
||||
/*
|
||||
* The section masks to add to the linkmap.
|
||||
*/
|
||||
const uint32_t sect_mask[] = {
|
||||
RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD,
|
||||
RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD,
|
||||
RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD,
|
||||
RTEMS_RTL_OBJ_SECT_BSS
|
||||
};
|
||||
const size_t sect_masks = sizeof (sect_mask) / sizeof (sect_mask[0]);
|
||||
|
||||
/*
|
||||
* Caculate the size of sections' name.
|
||||
*/
|
||||
|
||||
for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
mask <= RTEMS_RTL_OBJ_SECT_BSS;
|
||||
mask <<= 1)
|
||||
for (m = 0; m < sect_masks; ++m)
|
||||
{
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
while (!rtems_chain_is_tail (sections, node))
|
||||
{
|
||||
rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
|
||||
if ((sect->size != 0) && ((sect->flags & mask) != 0))
|
||||
const uint32_t mask = sect_mask[m];
|
||||
if ((sect->size != 0) && ((sect->flags & mask) == mask))
|
||||
{
|
||||
++sec_num;
|
||||
}
|
||||
@@ -1205,36 +1289,35 @@ rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
|
||||
for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
mask <= RTEMS_RTL_OBJ_SECT_BSS;
|
||||
mask <<= 1)
|
||||
for (m = 0; m < sect_masks; ++m)
|
||||
{
|
||||
sections = &obj->sections;
|
||||
node = rtems_chain_first (sections);
|
||||
while (!rtems_chain_is_tail (sections, node))
|
||||
{
|
||||
rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
|
||||
const uint32_t mask = sect_mask[m];
|
||||
|
||||
if ((sect->size != 0) && ((sect->flags & mask) != 0))
|
||||
if ((sect->size != 0) && ((sect->flags & mask) == mask))
|
||||
{
|
||||
sd[i].name = sect->name;
|
||||
sd[i].size = sect->size;
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_TEXT)
|
||||
if ((mask & RTEMS_RTL_OBJ_SECT_TEXT) != 0)
|
||||
{
|
||||
sd[i].rap_id = rap_text;
|
||||
sd[i].offset = sect->base - obj->text_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_CONST)
|
||||
if ((mask & RTEMS_RTL_OBJ_SECT_CONST) != 0)
|
||||
{
|
||||
sd[i].rap_id = rap_const;
|
||||
sd[i].offset = sect->base - obj->const_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_DATA)
|
||||
if ((mask & RTEMS_RTL_OBJ_SECT_DATA) != 0)
|
||||
{
|
||||
sd[i].rap_id = rap_data;
|
||||
sd[i].offset = sect->base - obj->data_base;
|
||||
}
|
||||
if (mask == RTEMS_RTL_OBJ_SECT_BSS)
|
||||
if ((mask & RTEMS_RTL_OBJ_SECT_BSS) != 0)
|
||||
{
|
||||
sd[i].rap_id = rap_bss;
|
||||
sd[i].offset = sect->base - obj->bss_base;
|
||||
|
||||
@@ -21,6 +21,12 @@
|
||||
#include <rtems/rtl/rtl-trace.h>
|
||||
#include "rtl-unwind.h"
|
||||
|
||||
/*
|
||||
* Set to 1 to allow untested relocations. If you tested one and it
|
||||
* works or you fixed the relocation please remove the guard.
|
||||
*/
|
||||
#define ALLOW_UNTESTED_RELOCS 1
|
||||
|
||||
/*
|
||||
* It is possible for the compiler to emit relocations for unaligned data.
|
||||
* We handle this situation with these inlines.
|
||||
@@ -341,8 +347,10 @@ rtems_rtl_elf_relor_rel (rtems_rtl_obj* obj,
|
||||
else {
|
||||
if (ELF_R_TYPE(rel->r_info) == R_TYPE(THM_JUMP24)) {
|
||||
tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
|
||||
#if !ALLOW_UNTESTED_RELOCS
|
||||
printf("THM_JUMP24 to arm not supported\n");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* THM_CALL bl-->blx */
|
||||
@@ -440,11 +448,33 @@ rtems_rtl_elf_relor_rel (rtems_rtl_obj* obj,
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
break;
|
||||
|
||||
case R_TYPE(TLS_LE32):
|
||||
#if ALLOW_UNTESTED_RELOCS
|
||||
if (!parsing) {
|
||||
addend = *where;
|
||||
*where = symvalue + addend;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
|
||||
printf ("rtl: TLS_LE32 %p @ %p in %s\n",
|
||||
(void *)*where, where, rtems_rtl_obj_oname (obj));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case R_TYPE(TLS_GD32):
|
||||
case R_TYPE(TLS_LDM32):
|
||||
case R_TYPE(TLS_LDO32):
|
||||
case R_TYPE(TLS_IE32):
|
||||
case R_TYPE(TLS_LDO12):
|
||||
case R_TYPE(TLS_LE12):
|
||||
case R_TYPE(TLS_IE12GP):
|
||||
printf("TSL relocations not supported\n");
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p, "
|
||||
"contents = %p\n",
|
||||
printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p",
|
||||
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)*where);
|
||||
(void *)rel->r_offset);
|
||||
if (!parsing)
|
||||
printf("contents = %p", (void *)*where);
|
||||
printf("\n");
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %" PRIu32 " "
|
||||
"in non-PLT relocations",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@@ -67,7 +68,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
|
||||
const Elf_Word symvalue)
|
||||
{
|
||||
(void) obj;
|
||||
(void) rela;
|
||||
(void) rel;
|
||||
(void) sect;
|
||||
(void) symname;
|
||||
(void) syminfo;
|
||||
@@ -147,12 +148,12 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
|
||||
break;
|
||||
|
||||
default:
|
||||
printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
|
||||
printf ("rtl: reloc unknown: sym = %i, type = %" PRIu32 ", offset = %p, "
|
||||
"contents = %p\n",
|
||||
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(int) ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
|
||||
(void *)rel->r_offset, (void *)*where);
|
||||
rtems_rtl_set_error (EINVAL,
|
||||
"%s: Unsupported relocation type %ld "
|
||||
"%s: Unsupported relocation type %" PRIu32 " "
|
||||
"in non-PLT relocations",
|
||||
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
|
||||
return false;
|
||||
|
||||
@@ -158,6 +158,16 @@ rtems_rtl_obj_unresolved_dependent (rtems_rtl_obj* obj,
|
||||
return ud->has_unresolved;
|
||||
}
|
||||
|
||||
static bool
|
||||
rtems_rtl_obj_unresolved_object (rtems_chain_node* node, void* data)
|
||||
{
|
||||
rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
|
||||
rtems_rtl_obj_unresolved_data* ud;
|
||||
ud = (rtems_rtl_obj_unresolved_data*) data;
|
||||
ud->has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0;
|
||||
return !ud->has_unresolved;
|
||||
}
|
||||
|
||||
bool
|
||||
rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
|
||||
{
|
||||
@@ -168,6 +178,15 @@ rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
|
||||
printf ("rtl: obj: unresolved: dep: %s is %s\n",
|
||||
obj->oname, ud.has_unresolved ? "unresolved" : "resolved");
|
||||
if (!ud.has_unresolved)
|
||||
{
|
||||
if ((obj->flags & RTEMS_RTL_OBJ_BASE) != 0)
|
||||
{
|
||||
rtems_rtl_data* rtl = rtems_rtl_data_unprotected ();
|
||||
rtems_rtl_chain_iterate (&rtl->objects,
|
||||
rtems_rtl_obj_unresolved_object,
|
||||
&ud);
|
||||
}
|
||||
else
|
||||
{
|
||||
rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
|
||||
obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
|
||||
@@ -176,6 +195,7 @@ rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
|
||||
&ud);
|
||||
rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
|
||||
}
|
||||
}
|
||||
return ud.has_unresolved;
|
||||
}
|
||||
|
||||
@@ -727,49 +747,57 @@ rtems_rtl_obj_iterate_dependents (rtems_rtl_obj* obj,
|
||||
size_t
|
||||
rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
return rtems_rtl_obj_section_size (obj, flags);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_text_alignment (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
|
||||
return rtems_rtl_obj_section_alignment (obj, flags);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_const_size (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_EH);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_EH);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
|
||||
return rtems_rtl_obj_section_size (obj, flags);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_const_alignment (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
|
||||
return rtems_rtl_obj_section_alignment (obj, flags);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
|
||||
{
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
|
||||
return rtems_rtl_obj_section_alignment (obj, flags);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
|
||||
{
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
|
||||
return rtems_rtl_obj_section_size (obj, flags);
|
||||
}
|
||||
|
||||
size_t
|
||||
rtems_rtl_obj_data_size (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
|
||||
return rtems_rtl_obj_section_size (obj, flags);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
rtems_rtl_obj_data_alignment (const rtems_rtl_obj* obj)
|
||||
{
|
||||
return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA);
|
||||
const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
|
||||
return rtems_rtl_obj_section_alignment (obj, flags);
|
||||
}
|
||||
|
||||
size_t
|
||||
@@ -790,8 +818,10 @@ rtems_rtl_obj_relocate (rtems_rtl_obj* obj,
|
||||
rtems_rtl_obj_sect_handler handler,
|
||||
void* data)
|
||||
{
|
||||
uint32_t mask = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_RELA;
|
||||
return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
|
||||
const uint32_t flags = (RTEMS_RTL_OBJ_SECT_LOAD |
|
||||
RTEMS_RTL_OBJ_SECT_REL |
|
||||
RTEMS_RTL_OBJ_SECT_RELA);
|
||||
return rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1012,11 +1042,13 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* This section is not to be loaded, clear the base.
|
||||
*/
|
||||
sect->base = 0;
|
||||
rtems_rtl_set_error (errno, "section has no load/clear op");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (sect->base)
|
||||
base_offset += sect->size;
|
||||
|
||||
++order;
|
||||
@@ -1054,6 +1086,8 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj* obj,
|
||||
* Set the sizes held in the object data. We need this for a fast reference.
|
||||
*/
|
||||
obj->text_size = text_size;
|
||||
obj->const_size = const_size;
|
||||
obj->data_size = data_size;
|
||||
obj->eh_size = eh_size;
|
||||
obj->bss_size = bss_size;
|
||||
|
||||
|
||||
@@ -128,17 +128,6 @@ typedef struct
|
||||
bool base; /**< Include the base object file. */
|
||||
} rtems_rtl_obj_print;
|
||||
|
||||
/**
|
||||
* Return the different between 2 void*.
|
||||
*/
|
||||
static size_t
|
||||
rtems_rtl_delta_voids (void* higher, void* lower)
|
||||
{
|
||||
char* ch = higher;
|
||||
char* cl = lower;
|
||||
return ch - cl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an argument.
|
||||
*/
|
||||
@@ -235,11 +224,11 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
|
||||
{
|
||||
printf ("%-*cexec size : %zi\n", print->indent, ' ', obj->exec_size);
|
||||
printf ("%-*ctext base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base));
|
||||
obj->text_base, obj->text_size);
|
||||
printf ("%-*cconst base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base));
|
||||
obj->const_base, obj->const_size);
|
||||
printf ("%-*cdata base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base));
|
||||
obj->data_base, obj->data_size);
|
||||
printf ("%-*cbss base : %p (%zi)\n", print->indent, ' ',
|
||||
obj->bss_base, obj->bss_size);
|
||||
}
|
||||
|
||||
@@ -36,13 +36,13 @@ rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
|
||||
*/
|
||||
size_t size =
|
||||
(sizeof(rtems_rtl_unresolv_block) +
|
||||
(sizeof(rtems_rtl_unresolv_rec) * (unresolved->block_recs - 1)));
|
||||
(sizeof(rtems_rtl_unresolv_rec) * unresolved->block_recs));
|
||||
rtems_rtl_unresolv_block* block =
|
||||
rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
|
||||
if (block)
|
||||
{
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: block-alloc %p\n", block);
|
||||
printf ("rtl: unresolv: block-alloc %p (%p)\n", block, block + size);
|
||||
rtems_chain_append (&unresolved->blocks, &block->link);
|
||||
}
|
||||
else
|
||||
@@ -53,28 +53,31 @@ rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
|
||||
static size_t
|
||||
rtems_rtl_unresolved_symbol_rec_count (size_t length)
|
||||
{
|
||||
return ((length + sizeof(rtems_rtl_unresolv_symbol) - 1) /
|
||||
sizeof(rtems_rtl_unresolv_symbol));
|
||||
const size_t rec_size = sizeof(rtems_rtl_unresolv_rec);
|
||||
const size_t rec_name_header = offsetof(rtems_rtl_unresolv_rec, rec.name.name);
|
||||
/*
|
||||
* Add on the nul and rmeove 1 to be inside a record.
|
||||
*/
|
||||
return ((length + rec_name_header - 1) / rec_size) + 1;
|
||||
}
|
||||
|
||||
|
||||
static size_t
|
||||
rtems_rtl_unresolved_symbol_recs (const char* name)
|
||||
{
|
||||
return rtems_rtl_unresolved_symbol_rec_count (strlen (name));
|
||||
return rtems_rtl_unresolved_symbol_rec_count (strlen (name) + 1);
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
|
||||
rtems_rtl_unresolv_rec* rec)
|
||||
{
|
||||
return (rec - &block->rec) / sizeof (rtems_rtl_unresolv_rec);
|
||||
return rec - &block->rec[0];
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec*
|
||||
rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block* block)
|
||||
{
|
||||
return &block->rec;
|
||||
return &block->rec[0];
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec*
|
||||
@@ -83,6 +86,7 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
|
||||
switch (rec->type)
|
||||
{
|
||||
case rtems_rtl_unresolved_empty:
|
||||
default:
|
||||
/*
|
||||
* Empty returns NULL. The end of the records in the block.
|
||||
*/
|
||||
@@ -99,9 +103,6 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
|
||||
case rtems_rtl_unresolved_reloc:
|
||||
++rec;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return rec;
|
||||
@@ -111,50 +112,121 @@ static bool
|
||||
rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block* block,
|
||||
rtems_rtl_unresolv_rec* rec)
|
||||
{
|
||||
int index = (rec - &block->rec) / sizeof (rec);
|
||||
return !rec || (index >= block->recs) || (rec->type == rtems_rtl_unresolved_empty);
|
||||
int index = rtems_rtl_unresolved_rec_index (block, rec);
|
||||
return (rec == NULL ||
|
||||
(index < 0) ||
|
||||
(index >= block->recs) ||
|
||||
(rec->type == rtems_rtl_unresolved_empty));
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_rec*
|
||||
rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block* block)
|
||||
{
|
||||
return &block->rec + block->recs;
|
||||
return &block->rec[0] + block->recs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name management iterator data.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char* name; /**< The name being searched for. */
|
||||
size_t length; /**< The length of the name. */
|
||||
rtems_rtl_unresolv_rec* rec; /**< The record being searched for. */
|
||||
int index; /**< The name's index. */
|
||||
int offset; /**< The offset to move the index. */
|
||||
} rtl_unresolved_name_data;
|
||||
|
||||
static bool
|
||||
rtems_rtl_unresolved_find_name_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
void* data)
|
||||
{
|
||||
rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
|
||||
if (rec->type == rtems_rtl_unresolved_symbol)
|
||||
{
|
||||
if ((rec->rec.name.length == nd->length)
|
||||
&& (strcmp (rec->rec.name.name, nd->name) == 0))
|
||||
{
|
||||
++rec->rec.name.refs;
|
||||
return true;
|
||||
}
|
||||
++nd->index;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
rtems_rtl_unresolved_find_name (rtems_rtl_unresolved* unresolved,
|
||||
const char* name,
|
||||
bool update_refcount)
|
||||
rtems_rtl_unresolved_find_name (const char* name)
|
||||
{
|
||||
size_t length = strlen (name) + 1;
|
||||
int index = 1;
|
||||
rtl_unresolved_name_data nd = {
|
||||
.name = name,
|
||||
.length = strlen (name) + 1,
|
||||
.rec = NULL,
|
||||
.index = 1,
|
||||
.offset = 0
|
||||
};
|
||||
if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_name_iterator,
|
||||
&nd))
|
||||
return nd.index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
|
||||
rtems_rtl_unresolv_rec* rec = rtems_rtl_unresolved_rec_first (block);
|
||||
|
||||
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
|
||||
static bool
|
||||
rtems_rtl_unresolved_find_index_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
void* data)
|
||||
{
|
||||
rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
|
||||
if (rec == nd->rec)
|
||||
return true;
|
||||
if (rec->type == rtems_rtl_unresolved_symbol)
|
||||
{
|
||||
if ((rec->rec.name.length == length)
|
||||
&& (strcmp (rec->rec.name.name, name) == 0))
|
||||
{
|
||||
if (update_refcount)
|
||||
++rec->rec.name.refs;
|
||||
return index;
|
||||
}
|
||||
++index;
|
||||
}
|
||||
rec = rtems_rtl_unresolved_rec_next (rec);
|
||||
++nd->index;
|
||||
return false;
|
||||
}
|
||||
|
||||
node = rtems_chain_next (node);
|
||||
static int
|
||||
rtems_rtl_unresolved_find_index (rtems_rtl_unresolv_rec* rec)
|
||||
{
|
||||
rtl_unresolved_name_data nd = {
|
||||
.name = NULL,
|
||||
.length = 0,
|
||||
.rec = rec,
|
||||
.index = 1,
|
||||
.offset = 0
|
||||
};
|
||||
if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_index_iterator,
|
||||
&nd))
|
||||
return nd.index;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0 - index;
|
||||
static bool
|
||||
rtems_rtl_unresolved_reindex_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
void* data)
|
||||
{
|
||||
rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
|
||||
/*
|
||||
* Reindexing only effects the reloc records.
|
||||
*/
|
||||
if (rec->type == rtems_rtl_unresolved_reloc)
|
||||
{
|
||||
if (rec->rec.reloc.name >= nd->index)
|
||||
rec->rec.reloc.name += nd->offset;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_unresolved_reindex_names (uint16_t index, int offset)
|
||||
{
|
||||
rtl_unresolved_name_data nd = {
|
||||
.name = NULL,
|
||||
.length = 0,
|
||||
.rec = NULL,
|
||||
.index = index,
|
||||
.offset = offset
|
||||
};
|
||||
rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_reindex_iterator,
|
||||
&nd);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,8 +256,8 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
|
||||
printf ("rtl: unresolv: resolve reloc: %s\n",
|
||||
rd->name_rec->rec.name.name);
|
||||
|
||||
rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);
|
||||
|
||||
if (rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym))
|
||||
{
|
||||
/*
|
||||
* If all unresolved externals are resolved add the obj module
|
||||
* to the pending queue. This will flush the object module's
|
||||
@@ -199,16 +271,18 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
|
||||
}
|
||||
|
||||
/*
|
||||
* Check Set the object pointer to NULL to indicate the record is not used
|
||||
* anymore. Update the reference count of the name. The sweep after
|
||||
* relocating will remove the reloc records with obj set to NULL and
|
||||
* names with a reference count of 0.
|
||||
* Set the object pointer to NULL to indicate the record is
|
||||
* not used anymore. Update the reference count of the name so
|
||||
* it can garbage collected if not referenced. The sweep after
|
||||
* relocating will remove the reloc records with obj set to
|
||||
* NULL and names with a reference count of 0.
|
||||
*/
|
||||
rec->rec.reloc.obj = NULL;
|
||||
if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
|
||||
--rd->name_rec->rec.name.refs;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -251,7 +325,7 @@ rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
typedef struct rtems_rtl_unresolved_archive_reloc_data
|
||||
{
|
||||
uint16_t name; /**< Name index. */
|
||||
bool loaded; /**< Object file loaded. */
|
||||
rtems_rtl_archive_search result; /**< The result of the load. */
|
||||
rtems_rtl_archives* archives; /**< The archives to search. */
|
||||
} rtems_rtl_unresolved_archive_reloc_data;
|
||||
|
||||
@@ -268,17 +342,18 @@ rtems_rtl_unresolved_archive_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
|
||||
if ((rec->rec.name.flags & RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE) != 0)
|
||||
{
|
||||
rtems_rtl_archive_search load;
|
||||
rtems_rtl_archive_search result;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: archive lookup: %d: %s\n",
|
||||
ard->name, rec->rec.name.name);
|
||||
|
||||
load = rtems_rtl_archive_obj_load (ard->archives,
|
||||
result = rtems_rtl_archive_obj_load (ard->archives,
|
||||
rec->rec.name.name, true);
|
||||
if (load == rtems_rtl_archive_search_loaded)
|
||||
if (result != rtems_rtl_archive_search_not_found)
|
||||
{
|
||||
ard->loaded = true;
|
||||
rec->rec.name.flags &= ~RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
|
||||
ard->result = result;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -292,10 +367,26 @@ rtems_rtl_unresolved_archive_search_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
void* data)
|
||||
{
|
||||
if (rec->type == rtems_rtl_unresolved_symbol)
|
||||
rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
|
||||
rec->rec.name.flags |= RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
|
||||
return false;
|
||||
}
|
||||
|
||||
static rtems_rtl_unresolv_block*
|
||||
rtems_rtl_unresolved_alloc_recs (rtems_rtl_unresolved* unresolved,
|
||||
size_t count)
|
||||
{
|
||||
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
|
||||
|
||||
if (block->recs + count <= unresolved->block_recs)
|
||||
return block;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
|
||||
rtems_rtl_unresolv_rec* rec,
|
||||
@@ -309,7 +400,7 @@ rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
|
||||
memmove (rec, rec + count, bytes);
|
||||
block->recs -= count;
|
||||
bytes = count * sizeof (rtems_rtl_unresolv_rec);
|
||||
memset (&block->rec + block->recs, 0, bytes);
|
||||
memset (&block->rec[block->recs], 0, bytes);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -328,51 +419,19 @@ rtems_rtl_unresolved_compact (void)
|
||||
{
|
||||
rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
|
||||
rtems_rtl_unresolv_rec* rec = rtems_rtl_unresolved_rec_first (block);
|
||||
|
||||
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
|
||||
{
|
||||
bool next_rec = true;
|
||||
|
||||
if (rec->type == rtems_rtl_unresolved_symbol)
|
||||
{
|
||||
++index;
|
||||
if (rec->rec.name.refs == 0)
|
||||
{
|
||||
/*
|
||||
* Iterate over the remaining reloc records and update the index.
|
||||
*/
|
||||
rtems_chain_node* reindex_node;
|
||||
rtems_rtl_unresolv_rec* reindex_first;
|
||||
size_t name_recs;
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: remove name: %s\n", rec->rec.name.name);
|
||||
reindex_node = node;
|
||||
reindex_first = rtems_rtl_unresolved_rec_next (rec);
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, reindex_node))
|
||||
{
|
||||
rtems_rtl_unresolv_rec* reindex_rec;
|
||||
rtems_rtl_unresolv_block* reindex_block;
|
||||
reindex_block = (rtems_rtl_unresolv_block*) reindex_node;
|
||||
if (reindex_first != NULL)
|
||||
{
|
||||
reindex_rec = reindex_first;
|
||||
reindex_first = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
reindex_rec = rtems_rtl_unresolved_rec_first (reindex_block);
|
||||
}
|
||||
while (!rtems_rtl_unresolved_rec_is_last (reindex_block,
|
||||
reindex_rec))
|
||||
{
|
||||
if (reindex_rec->type == rtems_rtl_unresolved_reloc)
|
||||
{
|
||||
if (reindex_rec->rec.reloc.name >= index)
|
||||
--reindex_rec->rec.reloc.name;
|
||||
}
|
||||
reindex_rec = rtems_rtl_unresolved_rec_next (reindex_rec);
|
||||
}
|
||||
reindex_node = rtems_chain_next (reindex_node);
|
||||
}
|
||||
rtems_rtl_unresolved_reindex_names (index, -1);
|
||||
/*
|
||||
* Compact the block removing the name record.
|
||||
*/
|
||||
@@ -470,11 +529,9 @@ rtems_rtl_unresolved_add (rtems_rtl_obj* obj,
|
||||
const rtems_rtl_word* rel)
|
||||
{
|
||||
rtems_rtl_unresolved* unresolved;
|
||||
rtems_chain_node* node;
|
||||
rtems_rtl_unresolv_block* block;
|
||||
rtems_rtl_unresolv_rec* rec;
|
||||
int name_index;
|
||||
size_t name_recs;
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
|
||||
@@ -485,69 +542,69 @@ rtems_rtl_unresolved_add (rtems_rtl_obj* obj,
|
||||
return false;
|
||||
|
||||
/*
|
||||
* Find the first block with a spare record.
|
||||
* Is the name present?
|
||||
*/
|
||||
node = rtems_chain_first (&unresolved->blocks);
|
||||
block = NULL;
|
||||
while (!rtems_chain_is_tail (&unresolved->blocks, node))
|
||||
{
|
||||
block = (rtems_rtl_unresolv_block*) node;
|
||||
if (block->recs < unresolved->block_recs)
|
||||
break;
|
||||
block = NULL;
|
||||
node = rtems_chain_next (node);
|
||||
}
|
||||
name_index = rtems_rtl_unresolved_find_name (name);
|
||||
|
||||
/*
|
||||
* No blocks with any spare records, allocate a new block.
|
||||
*/
|
||||
if (!block)
|
||||
{
|
||||
block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!block)
|
||||
return false;
|
||||
}
|
||||
|
||||
name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
|
||||
name_recs = rtems_rtl_unresolved_symbol_recs (name);
|
||||
|
||||
/*
|
||||
* An index less than 0 means the name is present and "0 - index" is the next
|
||||
* index to use.
|
||||
* An index less than 0 means the name was not found.
|
||||
*/
|
||||
if (name_index < 0)
|
||||
{
|
||||
rtems_rtl_unresolv_block* name_block = block;
|
||||
size_t name_recs;
|
||||
|
||||
name_recs = rtems_rtl_unresolved_symbol_recs (name);
|
||||
|
||||
/*
|
||||
* Is there enough room to fit the name ? It not add a new block.
|
||||
*/
|
||||
if (name_recs > (unresolved->block_recs - block->recs))
|
||||
{
|
||||
name_block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!name_block)
|
||||
return false;
|
||||
}
|
||||
|
||||
rec = rtems_rtl_unresolved_rec_first_free (name_block);
|
||||
rec->type = rtems_rtl_unresolved_symbol;
|
||||
rec->rec.name.refs = 1;
|
||||
rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
|
||||
rec->rec.name.length = strlen (name) + 1;
|
||||
memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
|
||||
block->recs += name_recs;
|
||||
name_index = 0 - name_index;
|
||||
|
||||
/*
|
||||
* If the name block is the reloc block and it is full allocate a new
|
||||
* block for the relocation record.
|
||||
*/
|
||||
if ((block == name_block) && (block->recs >= unresolved->block_recs))
|
||||
block = rtems_rtl_unresolved_alloc_recs (unresolved, name_recs);
|
||||
if (block == NULL)
|
||||
{
|
||||
block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!block)
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the record in the block.
|
||||
*/
|
||||
rec = rtems_rtl_unresolved_rec_first_free (block);
|
||||
|
||||
/*
|
||||
* Enter the new record before reindexing so the iterator can see
|
||||
* it and the iterator is called.
|
||||
*/
|
||||
rec->type = rtems_rtl_unresolved_symbol;
|
||||
rec->rec.name.refs = 1;
|
||||
rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
|
||||
rec->rec.name.length = strlen (name) + 1;
|
||||
memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length);
|
||||
block->recs += name_recs;
|
||||
|
||||
/*
|
||||
* Find the name index for the name and then reindex the names which
|
||||
* are moved up because of the insertion.
|
||||
*/
|
||||
name_index = rtems_rtl_unresolved_find_index (rec);
|
||||
if (name_index < 0)
|
||||
{
|
||||
rtems_rtl_set_error (ENOMEM, "internal unresolved block error");
|
||||
return false;
|
||||
}
|
||||
|
||||
rtems_rtl_unresolved_reindex_names (name_index, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first block with a spare record.
|
||||
*/
|
||||
block = rtems_rtl_unresolved_alloc_recs (unresolved, 1);
|
||||
if (block == NULL)
|
||||
{
|
||||
block = rtems_rtl_unresolved_block_alloc (unresolved);
|
||||
if (!block)
|
||||
return false;
|
||||
}
|
||||
|
||||
rec = rtems_rtl_unresolved_rec_first_free (block);
|
||||
@@ -592,7 +649,7 @@ rtems_rtl_unresolved_resolve (void)
|
||||
};
|
||||
rtems_rtl_unresolved_archive_reloc_data ard = {
|
||||
.name = 0,
|
||||
.loaded = false,
|
||||
.result = rtems_rtl_archive_search_not_found,
|
||||
.archives = rtems_rtl_archives_unprotected ()
|
||||
};
|
||||
|
||||
@@ -600,7 +657,7 @@ rtems_rtl_unresolved_resolve (void)
|
||||
rtems_rtl_unresolved_compact ();
|
||||
rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_iterator, &ard);
|
||||
|
||||
resolving = ard.loaded;
|
||||
resolving = ard.result == rtems_rtl_archive_search_loaded;
|
||||
}
|
||||
|
||||
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
|
||||
@@ -627,6 +684,7 @@ typedef struct rtems_rtl_unresolved_dump_data
|
||||
{
|
||||
size_t rec;
|
||||
size_t names;
|
||||
bool show_relocs;
|
||||
} rtems_rtl_unresolved_dump_data;
|
||||
|
||||
static bool
|
||||
@@ -642,14 +700,18 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
break;
|
||||
case rtems_rtl_unresolved_symbol:
|
||||
++dd->names;
|
||||
printf (" %3zu: 1: name: %3d refs: %2d: %2d: %s\n",
|
||||
printf (" %3zu: 1: name: %3d refs:%4d: flags:%04x %s (%d)\n",
|
||||
dd->rec, dd->names,
|
||||
rec->rec.name.refs, rec->rec.name.length, rec->rec.name.name);
|
||||
rec->rec.name.refs,
|
||||
rec->rec.name.flags,
|
||||
rec->rec.name.name,
|
||||
rec->rec.name.length);
|
||||
break;
|
||||
case rtems_rtl_unresolved_reloc:
|
||||
if (dd->show_relocs)
|
||||
printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
|
||||
dd->rec,
|
||||
rec->rec.reloc.obj->oname,
|
||||
rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
|
||||
rec->rec.reloc.name,
|
||||
rec->rec.reloc.sect);
|
||||
break;
|
||||
@@ -661,13 +723,6 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_unresolved_set_archive_search (void)
|
||||
{
|
||||
rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_unresolved_dump (void)
|
||||
{
|
||||
@@ -675,3 +730,10 @@ rtems_rtl_unresolved_dump (void)
|
||||
printf ("RTL Unresolved data:\n");
|
||||
rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_dump_iterator, &dd);
|
||||
}
|
||||
|
||||
void
|
||||
rtems_rtl_unresolved_set_archive_search (void)
|
||||
{
|
||||
rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
|
||||
NULL);
|
||||
}
|
||||
|
||||
@@ -144,7 +144,7 @@ rtems_rtl_data_init (void)
|
||||
/*
|
||||
* Open the archives.
|
||||
*/
|
||||
rtems_rtl_archives_open (&rtl->archives, "/etc/rtl-libs.conf");
|
||||
rtems_rtl_archives_open (&rtl->archives, "/etc/libdl.conf");
|
||||
|
||||
/*
|
||||
* Open the unresolved table.
|
||||
@@ -265,6 +265,14 @@ rtems_rtl_global_symbols (void)
|
||||
return &rtl->globals;
|
||||
}
|
||||
|
||||
const char*
|
||||
rtems_rtl_last_error_unprotected (void)
|
||||
{
|
||||
if (!rtl)
|
||||
return NULL;
|
||||
return rtl->last_error;
|
||||
}
|
||||
|
||||
rtems_chain_control*
|
||||
rtems_rtl_objects_unprotected (void)
|
||||
{
|
||||
|
||||
@@ -576,16 +576,19 @@ dl08-o5.o: dl08/dl-o5.c Makefile
|
||||
$(AM_V_CC)$(COMPILE) -c -o $@ $<
|
||||
dl08-o6-123456789-123456789.o: dl08/dl-o6-123456789-123456789.c Makefile
|
||||
$(AM_V_CC)$(COMPILE) -c -o $@ $<
|
||||
# echo "#" > etc/rtl-libs.conf
|
||||
# echo " # blah blah" >> etc/rtl-libs.conf
|
||||
etc/rtl-libs.conf:
|
||||
etc/libdl.conf:
|
||||
mkdir etc; \
|
||||
echo "/libdl08*.a" >> etc/rtl-libs.conf
|
||||
echo "#" > etc/libdl.conf
|
||||
echo " # blah blah" >> etc/libdl.conf
|
||||
echo "/libdl08*.a" >> etc/libdl.conf
|
||||
echo "" >> etc/libdl.conf
|
||||
echo "x" >> etc/libdl.conf
|
||||
echo "" >> etc/libdl.conf
|
||||
noinst_LIBRARIES = libdl08_1.a libdl08_2.a
|
||||
libdl08_1_a_SOURCES = dl08-o2.c dl08-o4.c
|
||||
libdl08_2_a_SOURCES = dl08-o3.c dl08-o5.c \
|
||||
dl08-o6-123456789-123456789.c
|
||||
dl08.tar: etc/rtl-libs.conf dl08-o1.o libdl08_1.a libdl08_2.a
|
||||
dl08.tar: etc/libdl.conf dl08-o1.o libdl08_1.a libdl08_2.a
|
||||
@rm -f $@
|
||||
$(AM_V_GEN)$(PAX) -w -f $@ $+
|
||||
dl08-tar.c: dl08.tar
|
||||
@@ -601,7 +604,7 @@ dl08$(EXEEXT): $(dl08_OBJECTS) $(dl08_DEPENDENCIES) dl08-sym.o
|
||||
$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
|
||||
CLEANFILES += dl08.pre dl08-sym.o libdl08_1.a libdl08_2.a dl08-o1.o dl08-o2.o \
|
||||
dl08-o3.o dl08-o4.o dl08-o5.o dl08-o6-123456789-123456789.o \
|
||||
dl08.tar dl08-tar.h etc/rtl-libs.conf
|
||||
dl08.tar dl08-tar.h etc/libdl.conf
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@@ -15,11 +15,13 @@
|
||||
RTEMS_RTL_TRACE_UNLOAD | \
|
||||
RTEMS_RTL_TRACE_SYMBOL | \
|
||||
RTEMS_RTL_TRACE_RELOC | \
|
||||
RTEMS_RTL_TRACE_LOAD_SECT | \
|
||||
RTEMS_RTL_TRACE_ALLOCATOR | \
|
||||
RTEMS_RTL_TRACE_UNRESOLVED | \
|
||||
RTEMS_RTL_TRACE_ARCHIVES | \
|
||||
RTEMS_RTL_TRACE_DEPENDENCY)
|
||||
#define DL_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
|
||||
/* RTEMS_RTL_TRACE_ALL */
|
||||
#define DL_DEBUG_TRACE DEBUG_TRACE
|
||||
#define DL_RTL_CMDS 1
|
||||
#else
|
||||
#define DL_DEBUG_TRACE 0
|
||||
|
||||
@@ -184,6 +184,12 @@ int dl_load_test(void)
|
||||
|
||||
dl_load_dump ();
|
||||
|
||||
/*
|
||||
* Check for any resolved externals.
|
||||
*/
|
||||
printf ("Check is any unresolved externals exist:\n");
|
||||
dl_check_resolved (RTLD_SELF, false);
|
||||
|
||||
printf ("Running rtems_main_o1:\n");
|
||||
if (dl_call (o[0].handle, "rtems_main_o1"))
|
||||
return 1;
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include "dl-load.h"
|
||||
#include "dl-o4.h"
|
||||
#include "dl-o5.h"
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
Reference in New Issue
Block a user