summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-05-03 10:15:20 +1000
committerChris Johns <chrisj@rtems.org>2019-05-03 10:15:20 +1000
commitb36c52097f52012f9a52dff6fc8393d63805158b (patch)
tree011b4cb678d343e0e6422d36bbcce982fdf48e30 /cpukit/libdl
parentbsp/motorola_powerpc: Fix debug output (diff)
downloadrtems-b36c52097f52012f9a52dff6fc8393d63805158b.tar.bz2
libdl: Do not access the ELF file while the allocator is locked.
- Load symbols before allocation. - Parse reloc records and place any reloc recs in a cache to use while the allocator is locked. - Relocate symbols after section allocation. - Split section loading into allocation/locating and loading. - Update all arch back-ends with a new reloc interface to control tramp handling. - Add `-a` and `-t` to the object list shell command. Closes #3741
Diffstat (limited to 'cpukit/libdl')
-rw-r--r--cpukit/libdl/rtl-allocator.c2
-rw-r--r--cpukit/libdl/rtl-elf.c484
-rw-r--r--cpukit/libdl/rtl-elf.h73
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c122
-rw-r--r--cpukit/libdl/rtl-mdreloc-bfin.c22
-rw-r--r--cpukit/libdl/rtl-mdreloc-h8300.c22
-rw-r--r--cpukit/libdl/rtl-mdreloc-i386.c18
-rw-r--r--cpukit/libdl/rtl-mdreloc-lm32.c21
-rw-r--r--cpukit/libdl/rtl-mdreloc-m68k.c174
-rw-r--r--cpukit/libdl/rtl-mdreloc-mips.c24
-rw-r--r--cpukit/libdl/rtl-mdreloc-moxie.c20
-rw-r--r--cpukit/libdl/rtl-mdreloc-powerpc.c69
-rw-r--r--cpukit/libdl/rtl-mdreloc-sparc.c26
-rw-r--r--cpukit/libdl/rtl-mdreloc-v850.c20
-rw-r--r--cpukit/libdl/rtl-obj.c138
-rw-r--r--cpukit/libdl/rtl-shell.c59
-rw-r--r--cpukit/libdl/rtl-trampoline.h94
-rw-r--r--cpukit/libdl/rtl-unresolved.c137
-rw-r--r--cpukit/libdl/rtl.c31
19 files changed, 1042 insertions, 514 deletions
diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c
index 0dca6b2f9a..647c0c89a4 100644
--- a/cpukit/libdl/rtl-allocator.c
+++ b/cpukit/libdl/rtl-allocator.c
@@ -147,7 +147,7 @@ rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address)
rtems_rtl_data* rtl = rtems_rtl_lock ();
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
- printf ("rtl: alloc: wr-enable: addr=%p\n", address);
+ printf ("rtl: alloc: wr-disable: addr=%p\n", address);
if (rtl != NULL && address != NULL)
rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE,
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 963cb4b2f4..0fa639f36f 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -1,5 +1,5 @@
/*
- * COPYRIGHT (c) 2012-2018 Chris Johns <chrisj@rtems.org>
+ * COPYRIGHT (c) 2012-2019 Chris Johns <chrisj@rtems.org>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -31,11 +31,12 @@
#include "rtl-elf.h"
#include "rtl-error.h"
#include <rtems/rtl/rtl-trace.h>
+#include "rtl-trampoline.h"
#include "rtl-unwind.h"
#include <rtems/rtl/rtl-unresolved.h>
/**
- * The offsets in the unresolved array.
+ * The offsets in the reloc words.
*/
#define REL_R_OFFSET (0)
#define REL_R_INFO (1)
@@ -166,66 +167,77 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
void* data)
{
rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
+ rtems_rtl_word rel_words[3];
+ rtems_rtl_elf_rel_status rs;
/*
- * 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.
+ * Check the reloc record to see if a trampoline is needed.
*/
- if (!resolved)
+ if (is_rela)
{
- ++rd->unresolved;
+ const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rela tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
+ ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
+ symname, (int) ELF_R_SYM (rela->r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
+ (uintmax_t) rela->r_offset, (int) rela->r_addend);
+ rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
+ symname, sym->st_info, symvalue);
+ rel_words[REL_R_OFFSET] = rela->r_offset;
+ rel_words[REL_R_INFO] = rela->r_info;
+ rel_words[REL_R_ADDEND] = rela->r_addend;
}
else
{
+ const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n",
+ ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
+ symname, (int) ELF_R_SYM (rel->r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
+ (uintmax_t) rel->r_offset);
+ rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
+ symname, sym->st_info, symvalue);
+ rel_words[REL_R_OFFSET] = rel->r_offset;
+ rel_words[REL_R_INFO] = rel->r_info;
+ rel_words[REL_R_ADDEND] = 0;
+ }
+
+ if (rs == rtems_rtl_elf_rel_failure)
+ return false;
+
+ if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add)
+ {
+ uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8);
+ if (!rtems_rtl_trampoline_add (obj, flags,
+ targetsect->section, symvalue, rel_words))
+ return false;
+ }
+
+ /*
+ * Handle any dependencies if there is a valid symbol.
+ */
+ if (symname != NULL)
+ {
/*
- * Check the reloc record to see if a trampoline is needed.
+ * Find the symbol's object file. It cannot be NULL so ignore that result
+ * if returned, it means something is corrupted. We are in an iterator.
*/
- if (is_rela)
- {
- const Elf_Rela* rela = (const Elf_Rela*) relbuf;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: rela tramp: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
- symname, (int) ELF_R_SYM (rela->r_info),
- (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
- (uintmax_t) rela->r_offset, (int) rela->r_addend);
- if (!rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
- symname, sym->st_info, symvalue))
- return false;
- }
- else
- {
- const Elf_Rel* rel = (const Elf_Rel*) relbuf;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: rel tramp: sym:%s(%d)=%08jx type:%d off:%08jx\n",
- symname, (int) ELF_R_SYM (rel->r_info),
- (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
- (uintmax_t) rel->r_offset);
- if (!rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
- symname, sym->st_info, symvalue))
- return false;
- }
-
- if (symname != NULL)
+ rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
+ if (sobj != NULL)
{
/*
- * Find the symbol's object file. It cannot be NULL so ignore that result
- * if returned, it means something is corrupted. We are in an iterator.
+ * A dependency is not the base kernel image or itself. Tag the object as
+ * having been visited so we count it only once.
*/
- rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
- if (sobj != NULL)
+ if (sobj != rtems_rtl_baseimage () && obj != sobj &&
+ (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
{
- /*
- * A dependency is not the base kernel image or itself. Tag the object as
- * having been visited so we count it only once.
- */
- if (sobj != rtems_rtl_baseimage () && obj != sobj &&
- (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
- {
- sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
- ++rd->dependents;
- }
+ sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
+ ++rd->dependents;
}
}
}
@@ -278,7 +290,8 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
}
else
{
- rtems_rtl_obj* sobj;
+ rtems_rtl_obj* sobj;
+ rtems_rtl_elf_rel_status rs;
if (is_rela)
{
@@ -287,8 +300,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend);
- if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
- symname, sym->st_info, symvalue))
+ rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
+ symname, sym->st_info, symvalue);
+ if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
else
@@ -298,8 +312,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset);
- if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
- symname, sym->st_info, symvalue))
+ rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
+ symname, sym->st_info, symvalue);
+ if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
@@ -419,7 +434,10 @@ 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 ||
+ if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT ||
+ ELF_ST_TYPE (sym.st_info) == STT_COMMON ||
+ ELF_ST_TYPE (sym.st_info) == STT_FUNC ||
+ ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
ELF_ST_TYPE (sym.st_info) == STT_TLS ||
sym.st_shndx == SHN_COMMON)
{
@@ -491,10 +509,11 @@ bool
rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
rtems_rtl_obj_sym* sym)
{
- rtems_rtl_obj_sect* sect;
- bool is_rela;
- Elf_Word symvalue;
- rtems_rtl_obj* sobj;
+ rtems_rtl_obj_sect* sect;
+ bool is_rela;
+ Elf_Word symvalue;
+ rtems_rtl_obj* sobj;
+ rtems_rtl_elf_rel_status rs;
is_rela = reloc->flags & 1;
@@ -516,8 +535,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n",
(int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
(uintmax_t) rela.r_offset, (int) rela.r_addend);
- if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
- sym->name, sym->data, symvalue))
+ rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
+ sym->name, sym->data, symvalue);
+ if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
else
@@ -529,8 +549,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
(int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
(uintmax_t) rel.r_offset);
- if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
- sym->name, sym->data, symvalue))
+ rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
+ sym->name, sym->data, symvalue);
+ if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
@@ -621,16 +642,117 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
return true;
}
+/**
+ * Struct to handle trampoline reloc recs in the unresolved table.
+ */
+typedef struct rtems_rtl_tramp_data
+{
+ bool failure;
+ rtems_rtl_obj* obj;
+ size_t count;
+ size_t total;
+} rtems_rtl_tramp_data;
+
+static bool
+rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
+ void* data)
+{
+ rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data;
+ if (rec->type == rtems_rtl_trampoline_reloc)
+ {
+ const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp;
+
+ ++td->total;
+
+ if (tramp->obj == td->obj)
+ {
+ const rtems_rtl_obj_sect* targetsect;
+ Elf_Byte st_info;
+ Elf_Word symvalue;
+ rtems_rtl_elf_rel_status rs;
+ bool* failure = (bool*) data;
+ const bool is_rela = (tramp->flags & 1) == 1;
+ const bool unresolved = (tramp->flags & (1 << 1)) != 0;
+
+ ++td->count;
+
+ targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect);
+ st_info = tramp->flags >> 8;
+ symvalue = tramp->symvalue;
+
+ if (is_rela)
+ {
+ Elf_Rela rela = {
+ .r_offset = tramp->rel[REL_R_OFFSET],
+ .r_info = tramp->rel[REL_R_INFO],
+ .r_addend = tramp->rel[REL_R_ADDEND]
+ };
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n",
+ ELF_ST_BIND (st_info) == STB_GLOBAL ||
+ ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
+ (int) ELF_R_SYM (rela.r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rela.r_info),
+ (uintmax_t) rela.r_offset, (int) rela.r_addend);
+ rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect,
+ NULL, st_info, symvalue);
+ }
+ else
+ {
+ Elf_Rel rel = {
+ .r_offset = tramp->rel[REL_R_OFFSET],
+ .r_info = tramp->rel[REL_R_INFO],
+ };
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n",
+ ELF_ST_BIND (st_info) == STB_GLOBAL ||
+ ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
+ (int) ELF_R_SYM (rel.r_info),
+ (uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info),
+ (uintmax_t) rel.r_offset);
+ rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect,
+ NULL, st_info, symvalue);
+ }
+
+ if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
+ tramp->obj->tramps_size += tramp->obj->tramp_size;
+ if (rs == rtems_rtl_elf_rel_failure)
+ {
+ *failure = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
static bool
rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
{
+ rtems_rtl_tramp_data td = { 0 };
+ td.obj = obj;
+ /*
+ * See which relocs are out of range and need a trampoline.
+ */
+ rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td);
+ if (td.failure)
+ return false;
+ rtems_rtl_trampoline_remove (obj);
+ obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n",
+ obj->tramp_relocs, td.count, td.total);
/*
* Add on enough space to handle the unresolved externals that need to be
* resolved at some point in time. They could all require fixups and
* trampolines.
*/
- obj->tramp_size +=
- rtems_rtl_elf_relocate_tramp_max_size () * unresolved;
+ obj->tramps_size += obj->tramp_size * unresolved;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: tramp:elf: slots: %zu (%zu)\n",
+ obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size,
+ obj->tramps_size);
return rtems_rtl_obj_alloc_trampoline (obj);
}
@@ -653,10 +775,10 @@ rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
}
static bool
-rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
- int fd,
- rtems_rtl_obj_sect* sect,
- void* data)
+rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ void* data)
{
rtems_rtl_obj_cache* symbols;
rtems_rtl_obj_cache* strings;
@@ -720,19 +842,20 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
* we need to make sure there is a valid seciton.
*/
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
- printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \
- "type:%-2d sect:%d size:%d\n",
+ printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d " \
+ "type:%-2d sect:%-5d size:%-5d value:%d\n",
sym, (int) symbol.st_name, name,
(int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info),
symbol.st_shndx,
- (int) symbol.st_size);
+ (int) symbol.st_size,
+ (int) symbol.st_value);
- /*
- * If a duplicate forget it.
- */
- if (rtems_rtl_symbol_global_find (name))
- continue;
+ /*
+ * 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) ||
@@ -775,7 +898,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
else
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
- printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n",
+ printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n",
sym, (int) symbol.st_name, name);
++globals;
global_string_space += strlen (name) + 1;
@@ -784,7 +907,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
- printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n",
+ printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n",
sym, (int) symbol.st_name, name);
++locals;
local_string_space += strlen (name) + 1;
@@ -849,14 +972,14 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
&symbol, sizeof (symbol)))
{
- if (locals)
+ if (obj->local_syms)
{
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
obj->local_table = NULL;
obj->local_size = 0;
obj->local_syms = 0;
}
- if (globals)
+ if (obj->global_syms)
{
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
obj->global_table = NULL;
@@ -875,78 +998,113 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
(ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
(ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
{
- rtems_rtl_obj_sect* symsect;
- rtems_rtl_obj_sym* osym;
- char* string;
- Elf_Word value;
+ rtems_rtl_obj_sym* osym;
+ char* string;
+ Elf_Word value;
+ const char* name;
- symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
- if (symsect)
+ 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))
+ {
+ osym = gsym;
+ string = gstring;
+ gstring += strlen (name) + 1;
+ ++gsym;
+ }
+ else
{
- const char* name;
+ osym = lsym;
+ string = lstring;
+ lstring += strlen (name) + 1;
+ ++lsym;
+ }
- off = obj->ooffset + strtab->offset + symbol.st_name;
- len = RTEMS_RTL_ELF_STRING_MAX;
+ /*
+ * Allocate any common symbols in the common section.
+ */
+ if (symbol.st_shndx == SHN_COMMON)
+ {
+ size_t value_off = rtems_rtl_obj_align (common_offset,
+ symbol.st_value);
+ common_offset = value_off + symbol.st_size;
+ value = value_off;
+ }
+ else
+ {
+ value = symbol.st_value;
+ }
- if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
- return false;
+ rtems_chain_set_off_chain (&osym->node);
+ memcpy (string, name, strlen (name) + 1);
+ osym->name = string;
+ osym->value = (uint8_t*) value;
+ osym->data = symbol.st_shndx;
- /*
- * If a duplicate forget it.
- */
- if (rtems_rtl_symbol_global_find (name))
- continue;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
+ "type:%-2d val:%-8p sect:%-3d size:%d\n",
+ sym, (int) symbol.st_name, osym->name,
+ (int) ELF_ST_BIND (symbol.st_info),
+ (int) ELF_ST_TYPE (symbol.st_info),
+ osym->value, symbol.st_shndx,
+ (int) symbol.st_size);
+ }
+ }
- if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
- (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
- {
- osym = gsym;
- string = gstring;
- gstring += strlen (name) + 1;
- ++gsym;
- }
- else
- {
- osym = lsym;
- string = lstring;
- lstring += strlen (name) + 1;
- ++lsym;
- }
+ return true;
+}
- /*
- * Allocate any common symbols in the common section.
- */
- if (symbol.st_shndx == SHN_COMMON)
- {
- size_t value_off = rtems_rtl_obj_align (common_offset,
- symbol.st_value);
- common_offset = value_off + symbol.st_size;
- value = value_off;
- }
- else
- {
- value = symbol.st_value;
- }
+static bool
+rtems_rtl_elf_symbols_locate (rtems_rtl_obj* obj,
+ int fd,
+ rtems_rtl_obj_sect* sect,
+ void* data)
+{
+ int sym;
- rtems_chain_set_off_chain (&osym->node);
- memcpy (string, name, strlen (name) + 1);
- osym->name = string;
- osym->value = value + (uint8_t*) symsect->base;
- osym->data = symbol.st_info;
+ for (sym = 0; sym < obj->local_syms; ++sym)
+ {
+ rtems_rtl_obj_sym* osym = &obj->local_table[sym];
+ rtems_rtl_obj_sect* symsect;
+ symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
+ if (symsect)
+ {
+ osym->value += (intptr_t) symsect->base;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+ printf ("rtl: sym:locate:local :%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
+ sym, osym->name, osym->value, osym->data,
+ symsect->name, symsect->base);
+ }
+ }
+ for (sym = 0; sym < obj->global_syms; ++sym)
+ {
+ rtems_rtl_obj_sym* osym = &obj->global_table[sym];
+ rtems_rtl_obj_sect* symsect;
+ symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
+ if (symsect)
+ {
+ osym->value += (intptr_t) symsect->base;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
- printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \
- "type:%-2d val:%8p sect:%d size:%d\n",
- sym, (int) symbol.st_name, osym->name,
- (int) ELF_ST_BIND (symbol.st_info),
- (int) ELF_ST_TYPE (symbol.st_info),
- osym->value, symbol.st_shndx,
- (int) symbol.st_size);
+ printf ("rtl: sym:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
+ sym, osym->name, osym->value, osym->data,
+ symsect->name, symsect->base);
}
- }
}
- if (globals)
+ if (obj->global_size)
rtems_rtl_symbol_obj_add (obj);
return true;
@@ -1435,6 +1593,11 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
}
/*
+ * Set the format's architecture's maximum tramp size.
+ */
+ obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size ();
+
+ /*
* Parse the section information first so we have the memory map of the object
* file and the memory allocated. Any further allocations we make to complete
* the load will not fragment the memory.
@@ -1443,18 +1606,31 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
return false;
/*
- * See if there are any common variables and if there are add a common
- * section.
+ * Set the entry point if there is one.
+ */
+ obj->entry = (void*)(uintptr_t) ehdr.e_entry;
+
+ /*
+ * Load the symbol table.
+ *
+ * 1. See if there are any common variables and if there are add a
+ * common section.
+ * 2. Add up the common.
+ * 3.
*/
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
return false;
if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
return false;
+ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &ehdr))
+ return false;
/*
- * Set the entry point if there is one.
+ * Parse the relocation records. It lets us know how many dependents
+ * and fixup trampolines there are.
*/
- obj->entry = (void*)(uintptr_t) ehdr.e_entry;
+ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
+ return false;
/*
* Lock the allocator so the section memory and the trampoline memory are as
@@ -1468,17 +1644,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
return false;
- /*
- * Load the sections and symbols and then relocation to the base address.
- */
- if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
- return false;
-
- /*
- * Parse the relocation records. It lets us know how many dependents
- * and fixup trampolines there are.
- */
- if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
+ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
return false;
if (!rtems_rtl_elf_dependents (obj, &relocs))
@@ -1492,9 +1658,15 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
*/
rtems_rtl_alloc_unlock ();
- if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
+ /*
+ * Load the sections and symbols and then relocation to the base address.
+ */
+ if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
+ /*
+ * Fix up the relocations.
+ */
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
return false;
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index 73d1e01bb1..660b0c47b4 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -52,6 +52,17 @@ extern "C" {
**/
/**
+ * ELF Relocation status codes.
+ */
+typedef enum rtems_rtl_elf_rel_status
+{
+ rtems_rtl_elf_rel_no_error, /**< There is no error processing the record. */
+ rtems_rtl_elf_rel_failure, /**< There was a failure processing the record. */
+ rtems_rtl_elf_rel_tramp_cache, /**< The reloc record may need a trampoliine. */
+ rtems_rtl_elf_rel_tramp_add /**< Add a trampoliine. */
+} rtems_rtl_elf_rel_status;
+
+/**
* Relocation trampoline relocation data.
*/
typedef struct rtems_rtl_mdreloc_trmap
@@ -143,20 +154,19 @@ size_t rtems_rtl_elf_relocate_tramp_max_size (void);
* relocation record requires a trampoline.
*
* @param obj The object file being relocated.
- * @param rel The ELF relocation record.
+ * @param rela The ELF relocation record.
* @param sect The section of the object file the relocation is for.
* @param symname The symbol's name.
* @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation is valid.
- * @retval bool The relocation is not valid.
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
*/
-bool rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
- const Elf_Rel* rel,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue);
+rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
/**
* Architecture specific relocation handler compiled in for a specific
@@ -169,15 +179,14 @@ bool rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
* @param symname The symbol's name.
* @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation is valid.
- * @retval bool The relocation is not valid.
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
*/
-bool rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
- const Elf_Rela* rela,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue);
+rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
/**
* Architecture specific relocation handler compiled in for a specific
@@ -190,15 +199,14 @@ bool rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
* @param symname The symbol's name.
* @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation has been applied.
- * @retval bool The relocation could not be applied.
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
*/
-bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
- const Elf_Rel* rel,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue);
+rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
+ const Elf_Rel* rel,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
/**
* Architecture specific relocation handler compiled in for a specific
@@ -211,15 +219,14 @@ bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
* @param symname The symbol's name.
* @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation has been applied.
- * @retval bool The relocation could not be applied.
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
*/
-bool rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
- const Elf_Rela* rela,
- const rtems_rtl_obj_sect* sect,
- const char* symname,
- const Elf_Byte syminfo,
- const Elf_Word symvalue);
+rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
+ const Elf_Rela* rela,
+ const rtems_rtl_obj_sect* sect,
+ const char* symname,
+ const Elf_Byte syminfo,
+ const Elf_Word symvalue);
/**
* The ELF format check handler.
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index b0c55c257a..4d5a2456a7 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -147,7 +147,7 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -162,10 +162,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -180,10 +180,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-static bool
+static rtems_rtl_elf_rel_status
rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -209,24 +209,37 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(CALL): /* BL/BLX */
case R_TYPE(JUMP24): /* B/BL<cond> */
- insn = *where;
-
- if (insn & 0x00800000)
- addend = insn | 0xff000000;
- else addend = insn & 0x00ffffff;
-
- if (isThumb(symvalue)) {
- if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
- else {
- if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
- *where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
- } else {
- printf("JUMP24 is not suppored from arm to thumb\n");
- return false;
+ if (parsing)
+ {
+ addend = 0;
+ }
+ else
+ {
+ insn = *where;
+
+ if (insn & 0x00800000)
+ addend = insn | 0xff000000;
+ else addend = insn & 0x00ffffff;
+
+ if (isThumb(symvalue)) {
+ if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
+ else {
+ if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
+ *where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
+ } else {
+ printf("JUMP24 is not suppored from arm to thumb\n");
+ return rtems_rtl_elf_rel_failure;
+ }
}
}
}
+ if (parsing && sect->base == 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP24/PC24/CALL tramp cache\n");
+ return rtems_rtl_elf_rel_tramp_cache;
+ }
+
tmp = symvalue + (addend << 2) - (Elf_Addr)where;
tmp = (Elf_Sword)tmp >> 2;
@@ -235,15 +248,16 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) {
- obj->tramp_size += tramp_size;
- return true;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP24/PC24/CALL tramp add\n");
+ return rtems_rtl_elf_rel_tramp_add;
}
- if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+ if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
rtems_rtl_set_error (EINVAL,
"%s: CALL/JUMP24: overflow: no tramp memory",
sect->name);
- return false;
+ return rtems_rtl_elf_rel_failure;
}
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
@@ -286,7 +300,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 16;
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
printf("MOVT_ABS Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
}
@@ -367,13 +381,22 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(THM_JUMP24):
/* same as THM_PC22; insn b.w */
case R_TYPE(THM_PC22):
- upper_insn = *(uint16_t *)where;
- lower_insn = *((uint16_t *)where + 1);
- sign = (upper_insn & (1 << 10)) >> 10;
- i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
- i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
- tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
- addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+ if (parsing)
+ {
+ addend = 0;
+ upper_insn = 0;
+ lower_insn = 0;
+ }
+ else
+ {
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+ sign = (upper_insn & (1 << 10)) >> 10;
+ i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
+ i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
+ tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
+ addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+ }
if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
else {
@@ -381,32 +404,40 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
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;
+ return rtems_rtl_elf_rel_failure;
#endif
}
else {
/* THM_CALL bl-->blx */
- lower_insn &=~(1<<12);
+ lower_insn &= ~(1<<12);
}
}
+ if (parsing && sect->base == 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_CALL/JUMP24 tramp cache\n");
+ return rtems_rtl_elf_rel_tramp_cache;
+ }
+
tmp = symvalue + addend;
tmp = tmp - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
- Elf_Word tramp_addr;
- size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
+ Elf_Word tramp_addr;
+ size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) {
- obj->tramp_size += tramp_size;
- return true;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: THM_CALL/JUMP24 tramp add: %08x - %p = %i\n",
+ symvalue + addend, where, (Elf_Sword) tmp);
+ return rtems_rtl_elf_rel_tramp_add;
}
- if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+ if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
rtems_rtl_set_error (EINVAL,
"%s: THM_CALL/JUMP24: overflow: no tramp memory",
sect->name);
- return false;
+ return rtems_rtl_elf_rel_failure;
}
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
@@ -438,7 +469,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
if (!isThumb(symvalue)) {
printf("THM_JUMP19 to arm not supported\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
upper_insn = *(uint16_t *)where;
@@ -463,8 +494,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
rtems_rtl_set_error (EINVAL, "%s: Overflow %" PRIu32 " "
"THM_JUMP19 relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
- return true;
- return false;
+ return rtems_rtl_elf_rel_failure;
}
sign = (tmp >> 20) & 0x1;
@@ -511,13 +541,13 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -534,7 +564,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
true);
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c
index af130276a4..27f865e5a5 100644
--- a/cpukit/libdl/rtl-mdreloc-bfin.c
+++ b/cpukit/libdl/rtl-mdreloc-bfin.c
@@ -73,7 +73,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -87,10 +87,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -136,7 +136,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
if ((tmp & 0xff000000) && (~tmp & 0xff800000)) {
printf("PCREL24/PCREL24_JU Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
tmp = (load_ptr(where) & 0x0000ff00) | ((tmp & 0x0000ffff) << 16) |
@@ -152,7 +152,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
if ((tmp & 0xfffff000) && (~tmp & 0xfffff800)) {
printf("PCREL12_JUMP_S Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
tmp = ((*(uint16_t *)where) & 0xf000) | (tmp & 0xfff);
@@ -161,15 +161,15 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default:
printf("Unspported rela type\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
memcpy((void*)where, &tmp, size);
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -184,10 +184,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -202,7 +202,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c
index 4a12f34f36..f1a52e4f9d 100644
--- a/cpukit/libdl/rtl-mdreloc-h8300.c
+++ b/cpukit/libdl/rtl-mdreloc-h8300.c
@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -80,10 +80,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -130,7 +130,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = symvalue + rela->r_addend - (Elf_Addr)where - 1;
if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){
printf("PCREL8 overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
} else {
*(uint8_t *)where = tmp;
}
@@ -141,7 +141,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = symvalue + rela->r_addend - (Elf_Addr)where - 2;
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){
printf("PCREL16 overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
} else {
*(uint16_t *)where = tmp;
}
@@ -150,12 +150,12 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default:
rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -170,10 +170,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -188,7 +188,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
index 576914cf04..40b09d4be2 100644
--- a/cpukit/libdl/rtl-mdreloc-i386.c
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -73,7 +73,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -88,10 +88,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rel,
const rtems_rtl_obj_sect* sect,
@@ -106,10 +106,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -123,10 +123,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -188,10 +188,10 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c
index 9f4606ebad..4d47592e12 100644
--- a/cpukit/libdl/rtl-mdreloc-lm32.c
+++ b/cpukit/libdl/rtl-mdreloc-lm32.c
@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -80,10 +80,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -151,7 +151,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = (Elf32_Sword)tmp >> 2;
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){
printf("BRANCH Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
*where = (*where & 0xffff0000) | (tmp & 0xffff);
@@ -164,17 +164,18 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default:
rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
printf("relocated address 0x%08lx\n", (Elf_Addr)where);
}
- return true;
+
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -189,10 +190,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -207,7 +208,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c
index 21a60ee62a..873574ef7c 100644
--- a/cpukit/libdl/rtl-mdreloc-m68k.c
+++ b/cpukit/libdl/rtl-mdreloc-m68k.c
@@ -86,7 +86,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -100,10 +100,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -118,91 +118,91 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
where = (Elf_Addr *)(sect->base + rela->r_offset);
switch (ELF_R_TYPE(rela->r_info)) {
- case R_TYPE(NONE):
- break;
-
- case R_TYPE(PC8):
- tmp = symvalue + rela->r_addend - (Elf_Addr)where;
- if (overflow_8_check(tmp))
- return false;
-
- *(uint8_t *)where = tmp;
-
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
- sect->name, (void*) (symvalue + rela->r_addend),
- (void *)*where, rtems_rtl_obj_oname (obj));
- break;
-
- case R_TYPE(PC16):
- tmp = symvalue + rela->r_addend - (Elf_Addr)where;
- if (overflow_16_check(tmp))
- return false;
-
- *(uint16_t*)where = tmp;
-
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
- sect->name, (void*) (symvalue + rela->r_addend),
- (void *)*where, rtems_rtl_obj_oname (obj));
- break;
- case R_TYPE(PC32):
- target = (Elf_Addr) symvalue + rela->r_addend;
- *where += target - (Elf_Addr)where;
-
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
- sect->name, (void*) (symvalue + rela->r_addend),
- (void *)*where, rtems_rtl_obj_oname (obj));
- break;
-
- case R_TYPE(GOT32):
- case R_TYPE(32):
- case R_TYPE(GLOB_DAT):
- target = (Elf_Addr) symvalue + rela->r_addend;
-
- if (*where != target)
- *where = target;
-
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
- sect->name, (void *)*where,
- rtems_rtl_obj_oname (obj));
- break;
-
- case R_TYPE(RELATIVE):
- *where += (Elf_Addr) sect->base + rela->r_addend;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: reloc RELATIVE in %s --> %p\n",
- rtems_rtl_obj_oname (obj), (void *)*where);
- break;
-
- case R_TYPE(COPY):
- /*
- * These are deferred until all other relocations have
- * been done. All we do here is make sure that the
- * COPY relocation is not in a shared library. They
- * are allowed only in executable files.
- */
- printf ("rtl: reloc COPY (please report)\n");
- break;
-
- default:
- printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
- "contents = %p\n",
- ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
- (void *)rela->r_offset, (void *)*where);
- rtems_rtl_set_error (EINVAL,
- "%s: Unsupported relocation type %d "
- "in non-PLT relocations",
- sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
- return false;
+ case R_TYPE(NONE):
+ break;
+
+ case R_TYPE(PC8):
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (overflow_8_check(tmp))
+ return rtems_rtl_elf_rel_failure;
+
+ *(uint8_t *)where = tmp;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(PC16):
+ tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+ if (overflow_16_check(tmp))
+ return rtems_rtl_elf_rel_failure;
+
+ *(uint16_t*)where = tmp;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+ case R_TYPE(PC32):
+ target = (Elf_Addr) symvalue + rela->r_addend;
+ *where += target - (Elf_Addr)where;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
+ sect->name, (void*) (symvalue + rela->r_addend),
+ (void *)*where, rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(GOT32):
+ case R_TYPE(32):
+ case R_TYPE(GLOB_DAT):
+ target = (Elf_Addr) symvalue + rela->r_addend;
+
+ if (*where != target)
+ *where = target;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
+ sect->name, (void *)*where,
+ rtems_rtl_obj_oname (obj));
+ break;
+
+ case R_TYPE(RELATIVE):
+ *where += (Elf_Addr) sect->base + rela->r_addend;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: reloc RELATIVE in %s --> %p\n",
+ rtems_rtl_obj_oname (obj), (void *)*where);
+ break;
+
+ case R_TYPE(COPY):
+ /*
+ * These are deferred until all other relocations have
+ * been done. All we do here is make sure that the
+ * COPY relocation is not in a shared library. They
+ * are allowed only in executable files.
+ */
+ printf ("rtl: reloc COPY (please report)\n");
+ break;
+
+ default:
+ printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
+ "contents = %p\n",
+ ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
+ (void *)rela->r_offset, (void *)*where);
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %d "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -217,10 +217,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -235,7 +235,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c
index f01a6552a5..c37804880f 100644
--- a/cpukit/libdl/rtl-mdreloc-mips.c
+++ b/cpukit/libdl/rtl-mdreloc-mips.c
@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -99,10 +99,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -116,7 +116,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
/*
@@ -127,7 +127,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
* symbol is STT_SECTION, it must be STB_LOCAL. Thus
* just consider symtype here.
*/
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -162,7 +162,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
tmp = symvalue + (int)tmp;
if ((tmp & 0xffff0000) != 0) {
printf("R_MIPS_16 Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
*where = (tmp & 0xffff) | (*where & 0xffff0000);
@@ -224,7 +224,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
t = ahl + (int16_t)addend;
tmp = symvalue;
if (tmp == 0)
- return false;
+ return rtems_rtl_elf_rel_failure;
addend &= 0xffff0000;
addend |= (uint16_t)(t + tmp);
@@ -254,7 +254,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 2;
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
printf("R_MIPS_PC16 Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
*where = (tmp & 0xffff) | (*where & 0xffff0000);
@@ -274,10 +274,10 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %ld "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c
index 68fa2d2a16..8c7169e532 100644
--- a/cpukit/libdl/rtl-mdreloc-moxie.c
+++ b/cpukit/libdl/rtl-mdreloc-moxie.c
@@ -67,7 +67,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -122,7 +122,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 1;
if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){
printf("Overflow for PCREL10: %ld exceed -0x200:0x1ff\n", tmp);
- return false;
+ return rtems_rtl_elf_rel_failure;
}
*(uint16_t *)where = (*(uint16_t *)where & 0xfc00) | (tmp & 0x3ff);
@@ -136,13 +136,13 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default:
rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -157,10 +157,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -175,7 +175,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
index 0a9703984d..48ecee58e5 100644
--- a/cpukit/libdl/rtl-mdreloc-powerpc.c
+++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
@@ -213,7 +213,14 @@ get_veneer_size (int type)
return rtems_rtl_elf_relocate_tramp_max_size ();
}
-static bool
+/**
+ * The offsets in the reloc words.
+ */
+#define REL_R_OFFSET (0)
+#define REL_R_INFO (1)
+#define REL_R_ADDEND (2)
+
+static rtems_rtl_elf_rel_status
rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -226,6 +233,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
Elf_Word tmp;
uint32_t mask = 0;
uint32_t bits = 0;
+ bool needs_tramp = false;
where = (Elf_Addr *)(sect->base + rela->r_offset);
switch (ELF_R_TYPE(rela->r_info)) {
@@ -259,14 +267,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 24;
mask = 0x3fffffc;
}
+
+ if (parsing && sect->base == 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR14/ADDR24 tramp cache\n");
+ return rtems_rtl_elf_rel_tramp_cache;
+ }
+
tmp = (symvalue + rela->r_addend) >> 2;
if (tmp > ((1<<bits) - 1 )) {
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) {
- obj->tramp_size += tramp_size;
- return true;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR14/ADDR24 tramp add\n");
+ return rtems_rtl_elf_rel_tramp_add;
+ }
+ if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: ADDR14/ADDR24 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
+ rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: ADDR14/ADDR24", sect->name);
+ return rtems_rtl_elf_rel_failure;
}
+ needs_tramp = true;
tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend);
@@ -283,7 +306,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) {
*where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
+ printf ("rtl: ADDR14/ADDR24%s %p @ %p in %s\n",
+ needs_tramp ? "(tramp)" : "",
(void *)*where, where, rtems_rtl_obj_oname (obj));
}
break;
@@ -341,15 +365,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 14;
}
+ if (parsing && sect->base == 0) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL24/REL14 tramp cache\n");
+ return rtems_rtl_elf_rel_tramp_cache;
+ }
+
tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
((Elf_Sword)tmp < -(1<<(bits-1)))) {
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) {
- obj->tramp_size += tramp_size;
- return true;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL24/REL14 tramp add\n");
+ return rtems_rtl_elf_rel_tramp_add;
+ }
+ if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL24/REL14 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
+ rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: REL24/REL14", sect->name);
+ return rtems_rtl_elf_rel_failure;
}
+ needs_tramp = true;
tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend);
@@ -367,7 +405,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) {
*where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: REL24/REL14 %p @ %p in %s\n",
+ printf ("rtl: REL24/REL14%s %p @ %p in %s\n",
+ needs_tramp ? "(tramp)" : "",
(void *)*where, where, rtems_rtl_obj_oname (obj));
}
break;
@@ -412,12 +451,12 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRId32
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -434,7 +473,7 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
true);
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -451,7 +490,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
false);
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -466,10 +505,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -484,7 +523,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
index f76da575e4..548c24132b 100644
--- a/cpukit/libdl/rtl-mdreloc-sparc.c
+++ b/cpukit/libdl/rtl-mdreloc-sparc.c
@@ -185,7 +185,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -199,10 +199,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -218,22 +218,22 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
type = ELF_R_TYPE(rela->r_info);
if (type == R_TYPE(NONE))
- return true;
+ return rtems_rtl_elf_rel_no_error;
/* We do JMP_SLOTs in _rtld_bind() below */
if (type == R_TYPE(JMP_SLOT))
- return true;
+ return rtems_rtl_elf_rel_no_error;
/* COPY relocs are also handled elsewhere */
if (type == R_TYPE(COPY))
- return true;
+ return rtems_rtl_elf_rel_no_error;
/*
* We use the fact that relocation types are an `enum'
* Note: R_SPARC_6 is currently numerically largest.
*/
if (type > R_TYPE(6))
- return false;
+ return rtems_rtl_elf_rel_failure;
value = rela->r_addend;
@@ -245,7 +245,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc relative in %s --> %p",
rtems_rtl_obj_oname (obj), (void *)*where);
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
if (RELOC_RESOLVE_SYMBOL (type)) {
@@ -315,10 +315,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
reloc_names[ELF_R_TYPE(rela->r_info)],
(void *)tmp, where, rtems_rtl_obj_oname (obj));
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -333,10 +333,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -351,7 +351,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
printf ("rtl: rel type record not supported; please report\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c
index 93e531b40e..859225ca6f 100644
--- a/cpukit/libdl/rtl-mdreloc-v850.c
+++ b/cpukit/libdl/rtl-mdreloc-v850.c
@@ -67,7 +67,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -125,7 +125,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) {
printf("Overflow\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
((uint16_t *)where)[0] = (*(uint16_t *)where & 0xffc0) |
@@ -145,13 +145,13 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default:
rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("error reloc type\n");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
- return true;
+ return rtems_rtl_elf_rel_no_error;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -166,10 +166,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
-bool
+rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -184,7 +184,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
- return false;
+ return rtems_rtl_elf_rel_failure;
}
bool
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 378678435d..9acb6f3943 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -583,10 +583,10 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
bool
rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
{
- if (obj->tramp_size == 0)
+ if (obj->tramps_size == 0)
return true;
obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
- obj->tramp_size,
+ obj->tramps_size,
true);
if (obj->trampoline == NULL)
rtems_rtl_set_error (ENOMEM, "no memory for the trampoline");
@@ -903,7 +903,7 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
if (obj->trampoline != NULL)
{
rtems_cache_instruction_sync_after_code_change(obj->trampoline,
- obj->tramp_size);
+ obj->tramps_size);
}
}
@@ -998,14 +998,11 @@ rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj)
}
}
-static bool
-rtems_rtl_obj_sections_loader (uint32_t mask,
- rtems_rtl_alloc_tag tag,
- rtems_rtl_obj* obj,
- int fd,
- uint8_t* base,
- rtems_rtl_obj_sect_handler handler,
- void* data)
+static void
+rtems_rtl_obj_sections_locate (uint32_t mask,
+ rtems_rtl_alloc_tag tag,
+ rtems_rtl_obj* obj,
+ uint8_t* base)
{
rtems_chain_control* sections = &obj->sections;
rtems_chain_node* node = rtems_chain_first (sections);
@@ -1013,9 +1010,7 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
int order = 0;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
- printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
-
- rtems_rtl_alloc_wr_enable (tag, base);
+ printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
while (!rtems_chain_is_tail (sections, node))
{
@@ -1032,32 +1027,11 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
- printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
+ printf ("rtl: locating:%2d: %s -> %p (s:%zi f:%04" PRIx32
" a:%" PRIu32 " l:%02d)\n",
order, sect->name, sect->base, sect->size,
sect->flags, sect->alignment, sect->link);
- if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
- {
- if (!handler (obj, fd, sect, data))
- {
- sect->base = 0;
- rtems_rtl_alloc_wr_disable (tag, base);
- return false;
- }
- }
- else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
- {
- memset (sect->base, 0, sect->size);
- }
- else
- {
- /*
- * This section is not to be loaded, clear the base.
- */
- sect->base = 0;
- }
-
if (sect->base)
base_offset += sect->size;
@@ -1070,10 +1044,6 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
node = rtems_chain_next (node);
}
-
- rtems_rtl_alloc_wr_disable (tag, base);
-
- return true;
}
bool
@@ -1159,6 +1129,94 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj,
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA, obj);
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, obj);
+ /*
+ * Locate all text, data and bss sections in seperate operations so each type of
+ * section is grouped together.
+ */
+ rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT,
+ rtems_rtl_alloc_text_tag (),
+ obj, obj->text_base);
+ rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST,
+ rtems_rtl_alloc_const_tag (),
+ obj, obj->const_base);
+ rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH,
+ rtems_rtl_alloc_eh_tag (),
+ obj, obj->eh_base);
+ rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA,
+ rtems_rtl_alloc_data_tag (),
+ obj, obj->data_base);
+ rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS,
+ rtems_rtl_alloc_bss_tag (),
+ obj, obj->bss_base);
+
+ return true;
+}
+
+static bool
+rtems_rtl_obj_sections_loader (uint32_t mask,
+ rtems_rtl_alloc_tag tag,
+ rtems_rtl_obj* obj,
+ int fd,
+ uint8_t* base,
+ rtems_rtl_obj_sect_handler handler,
+ void* data)
+{
+ rtems_chain_control* sections = &obj->sections;
+ rtems_chain_node* node = rtems_chain_first (sections);
+ int order = 0;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
+
+ rtems_rtl_alloc_wr_enable (tag, base);
+
+ while (!rtems_chain_is_tail (sections, node))
+ {
+ rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
+
+ if ((sect->size != 0) && ((sect->flags & mask) == mask))
+ {
+ if (sect->load_order == order)
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+ printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
+ " a:%" PRIu32 " l:%02d)\n",
+ order, sect->name, sect->base, sect->size,
+ sect->flags, sect->alignment, sect->link);
+
+ if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
+ {
+ if (!handler (obj, fd, sect, data))
+ {
+ sect->base = 0;
+ rtems_rtl_alloc_wr_disable (tag, base);
+ return false;
+ }
+ }
+ else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
+ {
+ memset (sect->base, 0, sect->size);
+ }
+ else
+ {
+ /*
+ * This section is not to be loaded, clear the base.
+ */
+ sect->base = 0;
+ }
+
+ ++order;
+
+ node = rtems_chain_first (sections);
+ continue;
+ }
+ }
+
+ node = rtems_chain_next (node);
+ }
+
+ rtems_rtl_alloc_wr_disable (tag, base);
+
return true;
}
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index 56418303ff..4c80ae5db1 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -143,6 +143,7 @@ typedef struct
bool memory_map; /**< Print the memory map. */
bool symbols; /**< Print the global symbols. */
bool dependencies; /**< Print any dependencies. */
+ bool trampolines; /**< Print trampoline stats. */
bool base; /**< Include the base object file. */
const char* re_name; /**< Name regx to filter on. */
const char* re_symbol; /**< Symbol regx to filter on. */
@@ -515,6 +516,8 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
rtems_printf (print->printer, "%-*cunresolved : %zu\n", indent, ' ', obj->unresolved);
rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users);
rtems_printf (print->printer, "%-*creferences : %zu\n", indent, ' ', obj->refs);
+ rtems_printf (print->printer, "%-*ctrampolines : %zu\n", indent, ' ',
+ rtems_rtl_obj_trampolines (obj));
rtems_printf (print->printer, "%-*csymbols : %zi\n", indent, ' ', obj->global_syms);
rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
}
@@ -535,6 +538,33 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
if (!dd.first)
rtems_printf (print->printer, "\n");
}
+ if (print->trampolines)
+ {
+ if (obj->tramp_size == 0)
+ {
+ rtems_printf (print->printer, "%-*ctrampolines: not supported\n", indent, ' ');
+ }
+ else
+ {
+ size_t slots = rtems_rtl_obj_trampoline_slots (obj);
+ size_t used = rtems_rtl_obj_trampolines (obj);
+ rtems_printf (print->printer, "%-*ctrampolines:\n", indent, ' ');
+ rtems_printf (print->printer, "%-*cslots : %zu\n", indent + 4, ' ',
+ slots);
+ rtems_printf (print->printer, "%-*csize : %zu\n", indent + 4, ' ',
+ obj->tramps_size);
+ rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ',
+ obj->tramp_size);
+ rtems_printf (print->printer, "%-*cused : %zu\n", indent + 4, ' ',
+ used);
+ rtems_printf (print->printer, "%-*crelocs : %zu\n", indent + 4, ' ',
+ obj->tramp_relocs);
+ rtems_printf (print->printer, "%-*cunresolved: %zu\n", indent + 4, ' ',
+ slots - obj->tramp_relocs);
+ rtems_printf (print->printer, "%-*cyield : %zu%%\n", indent + 4, ' ',
+ slots ? (used * 100) / slots : 0);
+ }
+ }
return true;
}
@@ -567,18 +597,31 @@ int
rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
{
rtems_rtl_obj_print print = { 0 };
- if (!rtems_rtl_check_opts (printer, "nlmsdb", argc, argv))
+ if (!rtems_rtl_check_opts (printer, "anlmsdbt", argc, argv))
return 1;
print.printer = printer;
print.indent = 1;
print.oname = true;
- print.names = rtems_rtl_parse_opt ('n', argc, argv);
- print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
- print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
- print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
- print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
- print.base = rtems_rtl_parse_opt ('b', argc, argv);;
- print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+ if (rtems_rtl_parse_opt ('a', argc, argv))
+ {
+ print.names = true;
+ print.stats = true;
+ print.memory_map = true;
+ print.symbols = true;
+ print.dependencies = true;
+ print.trampolines = true;
+ }
+ else
+ {
+ print.names = rtems_rtl_parse_opt ('n', argc, argv);
+ print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
+ print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
+ print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
+ print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
+ print.trampolines = rtems_rtl_parse_opt ('t', argc, argv);;
+ print.base = rtems_rtl_parse_opt ('b', argc, argv);;
+ print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+ }
print.re_symbol = NULL;
print.rtl = rtems_rtl_lock ();
if (print.rtl == NULL)
diff --git a/cpukit/libdl/rtl-trampoline.h b/cpukit/libdl/rtl-trampoline.h
new file mode 100644
index 0000000000..e04c20863b
--- /dev/null
+++ b/cpukit/libdl/rtl-trampoline.h
@@ -0,0 +1,94 @@
+/*
+ * COPYRIGHT (c) 2019 Chris Johns <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Trampoline Relocations Table.
+ *
+ * Cache relocation records that could result in a trampoline. The unresolved
+ * symbol table holds variable the symbol name (length string) and the object
+ * file's relocation records that reference the unresolved symbol. The
+ * trampoline cache is an extension to this table to reuse the code and memory
+ * and support trampolines.
+ *
+ * Some architectures require trampolines or veneers to extend the range of
+ * some instructions. The compiler generates small optimized instructions
+ * assuming most destinations are within the range of the instruction. The
+ * instructions are smaller in size and can have a number of encodings with
+ * different ranges. If a relocation record points to a symbol that is out of
+ * range for the instruction a trampoline is used to extend the instruction's
+ * range. A trampoline is a small fragment of architecture specific
+ * instructions located within the range of the relocation record instruction
+ * that can reach the entire address range. The trampoline's execution is
+ * transparent to the execution of the object file.
+ *
+ * An object file that needs a trampoline has a table allocated close to the
+ * text section. It has to be close to ensure the largest possible object file
+ * can be spported. The number of slots in a table depends on:
+ *
+ * # Location of the code
+ * # The type of relocation records in the object file
+ * # The instruction encoding the relocation record points too
+ * # The landing address of the instruction
+ *
+ * The allocation of the text segment and the trampoline table have to happen
+ * with the allocator lock being locked and held to make sure no other
+ * allocations happen inbetween the text section allocation and the trampoline
+ * table. Holding an allocator lock limits what the link editor can do when
+ * when the default heap allocator is being used. If calls any operating
+ * system services including the file system use the same allocator a deadlock
+ * will occur. This creates a conflict between performing the allocations
+ * together and reading the instructions while holding the allocator lock.
+ *
+ * The trampoline cache holds the parsed relocation records that could result
+ * in a trampoline. These records can be exaimined after the allocation of the
+ * text segment to determine how many relocation record target's are out of
+ * range. The minimum range for a specific type of relocation record has to be
+ * used as the instructions cannot be loaded.
+ */
+
+#if !defined (_RTEMS_RTL_TRAMPOLINE_H_)
+#define _RTEMS_RTL_TRAMPOLINE_H_
+
+#include <rtems/rtl/rtl-unresolved.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Add a relocation to the list of trampolinr relocations.
+ *
+ * @param obj The object table the relocation record is for.
+ * @param flags Format specific flags.
+ * @param sect The target section number the relocation references.
+ * @param symvalue The symbol's value.
+ * @param rel The format specific relocation data.
+ * @retval true The relocation has been added.
+ * @retval false The relocation could not be added.
+ */
+bool rtems_rtl_trampoline_add (rtems_rtl_obj* obj,
+ const uint16_t flags,
+ const uint16_t sect,
+ const rtems_rtl_word symvalue,
+ const rtems_rtl_word* rel);
+
+/**
+ * Remove the relocation records for an object file.
+ *
+ * @param obj The object table the symbols are for.
+ */
+void rtems_rtl_trampoline_remove (rtems_rtl_obj* obj);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index dc21e9bcc1..fbfe909d2e 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -27,6 +27,7 @@
#include "rtl-error.h"
#include <rtems/rtl/rtl-unresolved.h>
#include <rtems/rtl/rtl-trace.h>
+#include "rtl-trampoline.h"
static rtems_rtl_unresolv_block*
rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
@@ -69,7 +70,7 @@ rtems_rtl_unresolved_symbol_recs (const char* name)
static int
rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
- rtems_rtl_unresolv_rec* rec)
+ rtems_rtl_unresolv_rec* rec)
{
return rec - &block->rec[0];
}
@@ -101,6 +102,7 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
break;
case rtems_rtl_unresolved_reloc:
+ case rtems_rtl_trampoline_reloc:
++rec;
break;
}
@@ -403,6 +405,25 @@ rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
memset (&block->rec[block->recs], 0, bytes);
}
+static rtems_chain_node*
+rtems_rtl_unresolved_delete_block_if_empty (rtems_chain_control* blocks,
+ rtems_rtl_unresolv_block* block)
+{
+ rtems_chain_node* node = &block->link;
+ rtems_chain_node* next_node = rtems_chain_next (node);
+ /*
+ * Always leave a single block allocated. Eases possible heap fragmentation.
+ */
+ if (block->recs == 0 && !rtems_chain_has_only_one_node (blocks))
+ {
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: unresolv: block-del %p\n", block);
+ rtems_chain_extract (node);
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
+ }
+ return next_node;
+}
+
static void
rtems_rtl_unresolved_compact (void)
{
@@ -456,19 +477,8 @@ rtems_rtl_unresolved_compact (void)
rec = rtems_rtl_unresolved_rec_next (rec);
}
- if (block->recs == 0)
- {
- rtems_chain_node* next_node = rtems_chain_next (node);
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
- printf ("rtl: unresolv: block-del %p\n", block);
- rtems_chain_extract (node);
- rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
- node = next_node;
- }
- else
- {
- node = rtems_chain_next (node);
- }
+ node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
+ block);
}
}
}
@@ -480,7 +490,7 @@ rtems_rtl_unresolved_table_open (rtems_rtl_unresolved* unresolved,
unresolved->marker = 0xdeadf00d;
unresolved->block_recs = block_recs;
rtems_chain_initialize_empty (&unresolved->blocks);
- return true;
+ return rtems_rtl_unresolved_block_alloc (unresolved);
}
void
@@ -632,13 +642,13 @@ rtems_rtl_unresolved_resolve (void)
/*
* The resolving process is two separate stages, The first stage is to
- * iterate over the unresolved symbols search the global symbol table. If a
- * symbol is found iterate over the unresolved relocation records for the
+ * iterate over the unresolved symbols searching the global symbol table. If
+ * a symbol is found iterate over the unresolved relocation records for the
* symbol fixing up the relocations. The second stage is to search the
- * archives for symbols we have not been search before and if a symbol if
- * found in an archve loaded the object file. Loading an object file stops
- * the search of the archives for symbols and stage one is performed
- * again. The process repeats until no more symbols are resolved.
+ * archives for symbols we have not searched before and if a symbol is found
+ * in an archve load the object file. Loading an object file stops the
+ * search of the archives for symbols and stage one is performed again. The
+ * process repeats until no more symbols are resolved or there is an error.
*/
while (resolving)
{
@@ -665,18 +675,87 @@ rtems_rtl_unresolved_resolve (void)
}
bool
-rtems_rtl_unresolved_remove (rtems_rtl_obj* obj,
- const char* name,
- const uint16_t sect,
- const rtems_rtl_word* rel)
+rtems_rtl_trampoline_add (rtems_rtl_obj* obj,
+ const uint16_t flags,
+ const uint16_t sect,
+ const rtems_rtl_word symvalue,
+ const rtems_rtl_word* rel)
{
- rtems_rtl_unresolved* unresolved;
+ rtems_rtl_unresolved* unresolved;
+ rtems_rtl_unresolv_block* block;
+ rtems_rtl_unresolv_rec* rec;
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+ printf ("rtl: tramp: add: %s sect:%d flags:%04x\n",
+ rtems_rtl_obj_oname (obj), sect, flags);
+
unresolved = rtems_rtl_unresolved_unprotected ();
- if (unresolved == NULL)
+ if (!unresolved)
return false;
+
+ 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);
+ rec->type = rtems_rtl_trampoline_reloc;
+ rec->rec.tramp.obj = obj;
+ rec->rec.tramp.flags = flags;
+ rec->rec.tramp.sect = sect;
+ rec->rec.tramp.symvalue = symvalue;
+ rec->rec.tramp.rel[0] = rel[0];
+ rec->rec.tramp.rel[1] = rel[1];
+ rec->rec.tramp.rel[2] = rel[2];
+
+ ++block->recs;
+
return true;
}
+void
+rtems_rtl_trampoline_remove (rtems_rtl_obj* obj)
+{
+ rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
+ if (unresolved)
+ {
+ /*
+ * Iterate over the blocks clearing any trampoline records.
+ */
+ 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);
+
+ /*
+ * Search the table for a trampoline record and if found clean the
+ * record moving the remaining records down the block.
+ */
+ while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+ {
+ bool next_rec = true;
+
+ if (rec->type == rtems_rtl_trampoline_reloc && rec->rec.tramp.obj == obj)
+ {
+ rtems_rtl_unresolved_clean_block (block, rec, 1,
+ unresolved->block_recs);
+ next_rec = false;
+ }
+
+ if (next_rec)
+ rec = rtems_rtl_unresolved_rec_next (rec);
+ }
+
+ node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
+ block);
+ }
+ }
+}
+
/**
* Struct to pass relocation data in the iterator.
*/
@@ -708,8 +787,10 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
rec->rec.name.length);
break;
case rtems_rtl_unresolved_reloc:
+ case rtems_rtl_trampoline_reloc:
if (dd->show_relocs)
- printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
+ printf (" %3zu: 2:reloc%c: obj:%s name:%2d: sect:%d\n",
+ rec->type == rtems_rtl_unresolved_reloc ? 'R' : 'T',
dd->rec,
rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
rec->rec.reloc.name,
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
index e3dba5a206..d4103bace6 100644
--- a/cpukit/libdl/rtl.c
+++ b/cpukit/libdl/rtl.c
@@ -477,21 +477,24 @@ rtems_rtl_find_obj (const char* name)
rtems_rtl_obj*
rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
{
- rtems_chain_node* node = rtems_chain_first (&rtl->objects);
- while (!rtems_chain_is_tail (&rtl->objects, node))
+ if (sym != NULL)
{
- rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
- if (rtems_rtl_obj_has_symbol (obj, sym))
- return obj;
- node = rtems_chain_next (node);
- }
- node = rtems_chain_first (&rtl->pending);
- while (!rtems_chain_is_tail (&rtl->pending, node))
- {
- rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
- if (rtems_rtl_obj_has_symbol (obj, sym))
- return obj;
- node = rtems_chain_next (node);
+ rtems_chain_node* node = rtems_chain_first (&rtl->objects);
+ while (!rtems_chain_is_tail (&rtl->objects, node))
+ {
+ rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ if (rtems_rtl_obj_has_symbol (obj, sym))
+ return obj;
+ node = rtems_chain_next (node);
+ }
+ node = rtems_chain_first (&rtl->pending);
+ while (!rtems_chain_is_tail (&rtl->pending, node))
+ {
+ rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ if (rtems_rtl_obj_has_symbol (obj, sym))
+ return obj;
+ node = rtems_chain_next (node);
+ }
}
return NULL;
}