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
This commit is contained in:
Chris Johns
2019-05-03 10:15:20 +10:00
parent be50969881
commit b36c52097f
26 changed files with 1091 additions and 520 deletions

View File

@@ -227,10 +227,14 @@ struct rtems_rtl_obj
* obj. */ * obj. */
void* trampoline; /**< Trampoline memory. Used for fixups or void* trampoline; /**< Trampoline memory. Used for fixups or
* veneers */ * veneers */
size_t tramp_size; /**< Size of the tramopline memory. */ size_t tramp_size; /**< Size of a tramopline slot. */
size_t tramps_size; /**< Size of the trampoline memory. */
void* tramp_brk; /**< Trampoline memory allocator. MD void* tramp_brk; /**< Trampoline memory allocator. MD
* relocators can take memory from the * relocators can take memory from the
* break upto the size. */ * break upto the size. */
size_t tramp_relocs; /**< Number of slots reserved for
* relocs. The remainder are for
* unresolved symbols. */
struct link_map* linkmap; /**< For GDB. */ struct link_map* linkmap; /**< For GDB. */
void* loader; /**< The file details specific to a void* loader; /**< The file details specific to a
* loader. */ * loader. */
@@ -370,11 +374,35 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj,
* @param size The size to be allocated. * @param size The size to be allocated.
* @retval bool Returns @true if the space is available. * @retval bool Returns @true if the space is available.
*/ */
static inline bool rtems_rtl_obj_has_ramp_space (const rtems_rtl_obj* obj, static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj,
const size_t size) const size_t size)
{ {
return (obj->trampoline != NULL && return (obj->trampoline != NULL &&
((obj->tramp_brk - obj->trampoline) + size) <= obj->tramp_size); ((obj->tramp_brk - obj->trampoline) + size) <= obj->tramps_size);
}
/**
* Trampoline slots.
*
* @param obj The object file's descriptor.
* @retval size_t The number of trampoline slots.
*/
static inline size_t rtems_rtl_obj_trampoline_slots (const rtems_rtl_obj* obj)
{
return obj->trampoline == NULL || obj->tramp_size == 0 ?
0 : obj->tramps_size / obj->tramp_size;
}
/**
* Number of trampolines.
*
* @param obj The object file's descriptor.
* @retval size_t The number of trampolines.
*/
static inline size_t rtems_rtl_obj_trampolines (const rtems_rtl_obj* obj)
{
return obj->trampoline == NULL || obj->tramp_size == 0 ?
0 : (obj->tramp_brk - obj->trampoline) / obj->tramp_size;
} }
/** /**

View File

@@ -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 * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -73,7 +73,8 @@ typedef enum rtems_rtl_unresolved_rtype
{ {
rtems_rtl_unresolved_empty = 0, /**< The records is empty. Must always be 0 */ rtems_rtl_unresolved_empty = 0, /**< The records is empty. Must always be 0 */
rtems_rtl_unresolved_symbol = 1, /**< The record is a symbol. */ rtems_rtl_unresolved_symbol = 1, /**< The record is a symbol. */
rtems_rtl_unresolved_reloc = 2 /**< The record is a relocation record. */ rtems_rtl_unresolved_reloc = 2, /**< The record is a relocation record. */
rtems_rtl_trampoline_reloc = 3 /**< The record is a trampoline relocation record. */
} rtems_rtl_unresolved_rtype; } rtems_rtl_unresolved_rtype;
/** /**
@@ -101,7 +102,7 @@ typedef struct rtems_rtl_unresolv_symbol
/** /**
* Unresolved externals symbols require the relocation records to be held * Unresolved externals symbols require the relocation records to be held
* and references. * and referenced.
*/ */
typedef struct rtems_rtl_unresolv_reloc typedef struct rtems_rtl_unresolv_reloc
{ {
@@ -112,6 +113,18 @@ typedef struct rtems_rtl_unresolv_reloc
rtems_rtl_word rel[3]; /**< Relocation record. */ rtems_rtl_word rel[3]; /**< Relocation record. */
} rtems_rtl_unresolv_reloc; } rtems_rtl_unresolv_reloc;
/**
* Trampolines require the relocation records to be held
*/
typedef struct rtems_rtl_tramp_reloc
{
rtems_rtl_obj* obj; /**< The relocation's object file. */
uint16_t flags; /**< Format specific flags. */
uint16_t sect; /**< The target section. */
rtems_rtl_word symvalue; /**< The symbol's value. */
rtems_rtl_word rel[3]; /**< Relocation record. */
} rtems_rtl_tramp_reloc;
/** /**
* Unresolved externals records. * Unresolved externals records.
*/ */
@@ -121,7 +134,8 @@ typedef struct rtems_rtl_unresolv_rec
union union
{ {
rtems_rtl_unresolv_symbol name; /**< The symbol, or */ rtems_rtl_unresolv_symbol name; /**< The symbol, or */
rtems_rtl_unresolv_reloc reloc; /**< the relocation record. */ rtems_rtl_unresolv_reloc reloc; /**< The relocation record. */
rtems_rtl_tramp_reloc tramp; /**< The trampoline relocation record. */
} rec; } rec;
} rtems_rtl_unresolv_rec; } rtems_rtl_unresolv_rec;

View File

@@ -72,7 +72,7 @@ extern "C" {
/** /**
* The number of relocation record per block in the unresolved table. * The number of relocation record per block in the unresolved table.
*/ */
#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64) #define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (256)
/** /**
* The number of dependency record per block in the dependency table. * The number of dependency record per block in the dependency table.

View File

@@ -147,7 +147,7 @@ rtems_rtl_alloc_wr_disable (rtems_rtl_alloc_tag tag, void* address)
rtems_rtl_data* rtl = rtems_rtl_lock (); rtems_rtl_data* rtl = rtems_rtl_lock ();
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR)) 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) if (rtl != NULL && address != NULL)
rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE, rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE,

View File

@@ -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 * The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at * found in the file LICENSE in this distribution or at
@@ -31,11 +31,12 @@
#include "rtl-elf.h" #include "rtl-elf.h"
#include "rtl-error.h" #include "rtl-error.h"
#include <rtems/rtl/rtl-trace.h> #include <rtems/rtl/rtl-trace.h>
#include "rtl-trampoline.h"
#include "rtl-unwind.h" #include "rtl-unwind.h"
#include <rtems/rtl/rtl-unresolved.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_OFFSET (0)
#define REL_R_INFO (1) #define REL_R_INFO (1)
@@ -166,19 +167,9 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
void* data) void* data)
{ {
rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) 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.
*/
if (!resolved)
{
++rd->unresolved;
}
else
{
/* /*
* Check the reloc record to see if a trampoline is needed. * Check the reloc record to see if a trampoline is needed.
*/ */
@@ -186,27 +177,49 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
{ {
const Elf_Rela* rela = (const Elf_Rela*) relbuf; const Elf_Rela* rela = (const Elf_Rela*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rela tramp: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n", 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), symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend); (uintmax_t) rela->r_offset, (int) rela->r_addend);
if (!rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect, rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
symname, sym->st_info, symvalue)) symname, sym->st_info, symvalue);
return false; 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 else
{ {
const Elf_Rel* rel = (const Elf_Rel*) relbuf; const Elf_Rel* rel = (const Elf_Rel*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rel tramp: sym:%s(%d)=%08jx type:%d off:%08jx\n", 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), symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset); (uintmax_t) rel->r_offset);
if (!rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect, rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
symname, sym->st_info, symvalue)) 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; return false;
} }
/*
* Handle any dependencies if there is a valid symbol.
*/
if (symname != NULL) if (symname != NULL)
{ {
/* /*
@@ -228,7 +241,6 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
} }
} }
} }
}
return true; return true;
} }
@@ -279,6 +291,7 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
else else
{ {
rtems_rtl_obj* sobj; rtems_rtl_obj* sobj;
rtems_rtl_elf_rel_status rs;
if (is_rela) if (is_rela)
{ {
@@ -287,8 +300,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rela->r_info), symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend); (uintmax_t) rela->r_offset, (int) rela->r_addend);
if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
symname, sym->st_info, symvalue)) symname, sym->st_info, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false; return false;
} }
else else
@@ -298,8 +312,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rel->r_info), symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset); (uintmax_t) rel->r_offset);
if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
symname, sym->st_info, symvalue)) symname, sym->st_info, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false; 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. * 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 || ELF_ST_TYPE (sym.st_info) == STT_TLS ||
sym.st_shndx == SHN_COMMON) sym.st_shndx == SHN_COMMON)
{ {
@@ -495,6 +513,7 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
bool is_rela; bool is_rela;
Elf_Word symvalue; Elf_Word symvalue;
rtems_rtl_obj* sobj; rtems_rtl_obj* sobj;
rtems_rtl_elf_rel_status rs;
is_rela = reloc->flags & 1; 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", 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), (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
(uintmax_t) rela.r_offset, (int) rela.r_addend); (uintmax_t) rela.r_offset, (int) rela.r_addend);
if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect, rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
sym->name, sym->data, symvalue)) sym->name, sym->data, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false; return false;
} }
else 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", printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
(int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info), (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
(uintmax_t) rel.r_offset); (uintmax_t) rel.r_offset);
if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect, rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
sym->name, sym->data, symvalue)) sym->name, sym->data, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false; return false;
} }
@@ -621,16 +642,117 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
return true; 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 static bool
rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) 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 * 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 * resolved at some point in time. They could all require fixups and
* trampolines. * trampolines.
*/ */
obj->tramp_size += obj->tramps_size += obj->tramp_size * unresolved;
rtems_rtl_elf_relocate_tramp_max_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); return rtems_rtl_obj_alloc_trampoline (obj);
} }
@@ -653,7 +775,7 @@ rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
} }
static bool static bool
rtems_rtl_elf_symbols (rtems_rtl_obj* obj, rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj,
int fd, int fd,
rtems_rtl_obj_sect* sect, rtems_rtl_obj_sect* sect,
void* data) void* data)
@@ -720,13 +842,14 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
* we need to make sure there is a valid seciton. * we need to make sure there is a valid seciton.
*/ */
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \ printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d " \
"type:%-2d sect:%d size:%d\n", "type:%-2d sect:%-5d size:%-5d value:%d\n",
sym, (int) symbol.st_name, name, sym, (int) symbol.st_name, name,
(int) ELF_ST_BIND (symbol.st_info), (int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info), (int) ELF_ST_TYPE (symbol.st_info),
symbol.st_shndx, symbol.st_shndx,
(int) symbol.st_size); (int) symbol.st_size,
(int) symbol.st_value);
/* /*
* If a duplicate forget it. * If a duplicate forget it.
@@ -775,7 +898,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
else else
{ {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) 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); sym, (int) symbol.st_name, name);
++globals; ++globals;
global_string_space += strlen (name) + 1; 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) else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
{ {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) 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); sym, (int) symbol.st_name, name);
++locals; ++locals;
local_string_space += strlen (name) + 1; 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, if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
&symbol, sizeof (symbol))) &symbol, sizeof (symbol)))
{ {
if (locals) if (obj->local_syms)
{ {
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
obj->local_table = NULL; obj->local_table = NULL;
obj->local_size = 0; obj->local_size = 0;
obj->local_syms = 0; obj->local_syms = 0;
} }
if (globals) if (obj->global_syms)
{ {
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
obj->global_table = NULL; obj->global_table = NULL;
@@ -875,14 +998,9 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
(ELF_ST_BIND (symbol.st_info) == STB_WEAK) || (ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
(ELF_ST_BIND (symbol.st_info) == STB_LOCAL))) (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
{ {
rtems_rtl_obj_sect* symsect;
rtems_rtl_obj_sym* osym; rtems_rtl_obj_sym* osym;
char* string; char* string;
Elf_Word value; Elf_Word value;
symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
if (symsect)
{
const char* name; const char* name;
off = obj->ooffset + strtab->offset + symbol.st_name; off = obj->ooffset + strtab->offset + symbol.st_name;
@@ -931,12 +1049,12 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
rtems_chain_set_off_chain (&osym->node); rtems_chain_set_off_chain (&osym->node);
memcpy (string, name, strlen (name) + 1); memcpy (string, name, strlen (name) + 1);
osym->name = string; osym->name = string;
osym->value = value + (uint8_t*) symsect->base; osym->value = (uint8_t*) value;
osym->data = symbol.st_info; osym->data = symbol.st_shndx;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \ printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
"type:%-2d val:%8p sect:%d size:%d\n", "type:%-2d val:%-8p sect:%-3d size:%d\n",
sym, (int) symbol.st_name, osym->name, sym, (int) symbol.st_name, osym->name,
(int) ELF_ST_BIND (symbol.st_info), (int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info), (int) ELF_ST_TYPE (symbol.st_info),
@@ -944,9 +1062,49 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
(int) symbol.st_size); (int) symbol.st_size);
} }
} }
return true;
}
static bool
rtems_rtl_elf_symbols_locate (rtems_rtl_obj* obj,
int fd,
rtems_rtl_obj_sect* sect,
void* data)
{
int sym;
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);
}
} }
if (globals) 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:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
sym, osym->name, osym->value, osym->data,
symsect->name, symsect->base);
}
}
if (obj->global_size)
rtems_rtl_symbol_obj_add (obj); rtems_rtl_symbol_obj_add (obj);
return true; return true;
@@ -1434,6 +1592,11 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
return false; return false;
} }
/*
* 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 * 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 * file and the memory allocated. Any further allocations we make to complete
@@ -1443,18 +1606,31 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
return false; return false;
/* /*
* See if there are any common variables and if there are add a common * Set the entry point if there is one.
* section. */
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)) if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
return false; return false;
if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment)) if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
return false; 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 * 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)) if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
return false; return false;
/* if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &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;
/*
* 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))
return false; return false;
if (!rtems_rtl_elf_dependents (obj, &relocs)) 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 (); 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; return false;
/*
* Fix up the relocations.
*/
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr)) if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
return false; return false;

View File

@@ -51,6 +51,17 @@ extern "C" {
** Imported NetBSD ELF Specifics End. ** Imported NetBSD ELF Specifics End.
**/ **/
/**
* 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. * Relocation trampoline relocation data.
*/ */
@@ -143,15 +154,14 @@ size_t rtems_rtl_elf_relocate_tramp_max_size (void);
* relocation record requires a trampoline. * relocation record requires a trampoline.
* *
* @param obj The object file being relocated. * @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 sect The section of the object file the relocation is for.
* @param symname The symbol's name. * @param symname The symbol's name.
* @param syminfo The ELF symbol info field. * @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value. * @param symvalue If a symbol is referenced, this is the symbols value.
* @retval bool The relocation is valid. * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
* @retval bool The relocation is not valid.
*/ */
bool rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
const char* symname, const char* symname,
@@ -169,10 +179,9 @@ bool rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
* @param symname The symbol's name. * @param symname The symbol's name.
* @param syminfo The ELF symbol info field. * @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value. * @param symvalue If a symbol is referenced, this is the symbols value.
* @retval bool The relocation is valid. * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
* @retval bool The relocation is not valid.
*/ */
bool rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
const char* symname, const char* symname,
@@ -190,10 +199,9 @@ bool rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
* @param symname The symbol's name. * @param symname The symbol's name.
* @param syminfo The ELF symbol info field. * @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value. * @param symvalue If a symbol is referenced, this is the symbols value.
* @retval bool The relocation has been applied. * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
* @retval bool The relocation could not be applied.
*/ */
bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
const char* symname, const char* symname,
@@ -211,10 +219,9 @@ bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
* @param symname The symbol's name. * @param symname The symbol's name.
* @param syminfo The ELF symbol info field. * @param syminfo The ELF symbol info field.
* @param symvalue If a symbol is referenced, this is the symbols value. * @param symvalue If a symbol is referenced, this is the symbols value.
* @retval bool The relocation has been applied. * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
* @retval bool The relocation could not be applied.
*/ */
bool rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj, rtems_rtl_elf_rel_status rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
const char* symname, const char* symname,

View File

@@ -147,7 +147,7 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true; return true;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -162,10 +162,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -180,10 +180,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -209,6 +209,12 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(CALL): /* BL/BLX */ case R_TYPE(CALL): /* BL/BLX */
case R_TYPE(JUMP24): /* B/BL<cond> */ case R_TYPE(JUMP24): /* B/BL<cond> */
if (parsing)
{
addend = 0;
}
else
{
insn = *where; insn = *where;
if (insn & 0x00800000) if (insn & 0x00800000)
@@ -222,10 +228,17 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
*where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */ *where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
} else { } else {
printf("JUMP24 is not suppored from arm to thumb\n"); printf("JUMP24 is not suppored from arm to thumb\n");
return false; 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 = symvalue + (addend << 2) - (Elf_Addr)where;
tmp = (Elf_Sword)tmp >> 2; 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)); size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) { if (parsing) {
obj->tramp_size += tramp_size; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
return true; 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, rtems_rtl_set_error (EINVAL,
"%s: CALL/JUMP24: overflow: no tramp memory", "%s: CALL/JUMP24: overflow: no tramp memory",
sect->name); sect->name);
return false; return rtems_rtl_elf_rel_failure;
} }
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1); 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; tmp = (Elf_Sword)tmp >> 16;
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) { if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
printf("MOVT_ABS Overflow\n"); printf("MOVT_ABS Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
} }
@@ -367,6 +381,14 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(THM_JUMP24): case R_TYPE(THM_JUMP24):
/* same as THM_PC22; insn b.w */ /* same as THM_PC22; insn b.w */
case R_TYPE(THM_PC22): case R_TYPE(THM_PC22):
if (parsing)
{
addend = 0;
upper_insn = 0;
lower_insn = 0;
}
else
{
upper_insn = *(uint16_t *)where; upper_insn = *(uint16_t *)where;
lower_insn = *((uint16_t *)where + 1); lower_insn = *((uint16_t *)where + 1);
sign = (upper_insn & (1 << 10)) >> 10; sign = (upper_insn & (1 << 10)) >> 10;
@@ -374,6 +396,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
i2 = ((lower_insn >> 11) & 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); tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24); addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
}
if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */ if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
else { else {
@@ -381,15 +404,21 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */ tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
#if !ALLOW_UNTESTED_RELOCS #if !ALLOW_UNTESTED_RELOCS
printf("THM_JUMP24 to arm not supported\n"); printf("THM_JUMP24 to arm not supported\n");
return false; return rtems_rtl_elf_rel_failure;
#endif #endif
} }
else { else {
/* THM_CALL bl-->blx */ /* 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 = symvalue + addend;
tmp = tmp - (Elf_Addr)where; tmp = tmp - (Elf_Addr)where;
@@ -398,15 +427,17 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info)); size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) { if (parsing) {
obj->tramp_size += tramp_size; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
return true; 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, rtems_rtl_set_error (EINVAL,
"%s: THM_CALL/JUMP24: overflow: no tramp memory", "%s: THM_CALL/JUMP24: overflow: no tramp memory",
sect->name); sect->name);
return false; return rtems_rtl_elf_rel_failure;
} }
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1); 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)) { if (!isThumb(symvalue)) {
printf("THM_JUMP19 to arm not supported\n"); printf("THM_JUMP19 to arm not supported\n");
return false; return rtems_rtl_elf_rel_failure;
} }
upper_insn = *(uint16_t *)where; 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 " " rtems_rtl_set_error (EINVAL, "%s: Overflow %" PRIu32 " "
"THM_JUMP19 relocations", "THM_JUMP19 relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return true; return rtems_rtl_elf_rel_failure;
return false;
} }
sign = (tmp >> 20) & 0x1; sign = (tmp >> 20) & 0x1;
@@ -511,13 +541,13 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRIu32 " " "%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations", "in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -534,7 +564,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
true); true);
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,

View File

@@ -73,7 +73,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -87,10 +87,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -136,7 +136,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
if ((tmp & 0xff000000) && (~tmp & 0xff800000)) { if ((tmp & 0xff000000) && (~tmp & 0xff800000)) {
printf("PCREL24/PCREL24_JU Overflow\n"); printf("PCREL24/PCREL24_JU Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
tmp = (load_ptr(where) & 0x0000ff00) | ((tmp & 0x0000ffff) << 16) | 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)) { if ((tmp & 0xfffff000) && (~tmp & 0xfffff800)) {
printf("PCREL12_JUMP_S Overflow\n"); printf("PCREL12_JUMP_S Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
tmp = ((*(uint16_t *)where) & 0xf000) | (tmp & 0xfff); tmp = ((*(uint16_t *)where) & 0xf000) | (tmp & 0xfff);
@@ -161,15 +161,15 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default: default:
printf("Unspported rela type\n"); printf("Unspported rela type\n");
return false; return rtems_rtl_elf_rel_failure;
} }
memcpy((void*)where, &tmp, size); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -184,10 +184,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -202,7 +202,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -80,10 +80,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, 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; tmp = symvalue + rela->r_addend - (Elf_Addr)where - 1;
if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){ if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){
printf("PCREL8 overflow\n"); printf("PCREL8 overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} else { } else {
*(uint8_t *)where = tmp; *(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; tmp = symvalue + rela->r_addend - (Elf_Addr)where - 2;
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){ if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){
printf("PCREL16 overflow\n"); printf("PCREL16 overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} else { } else {
*(uint16_t *)where = tmp; *(uint16_t *)where = tmp;
} }
@@ -150,12 +150,12 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default: default:
rtems_rtl_set_error (EINVAL, "rela type record not supported"); rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n"); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -170,10 +170,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -188,7 +188,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -73,7 +73,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -88,10 +88,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rel, const Elf_Rela* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -106,10 +106,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -123,10 +123,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -188,10 +188,10 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRIu32 " " "%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations", "in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); 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 bool

View File

@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -80,10 +80,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -151,7 +151,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = (Elf32_Sword)tmp >> 2; tmp = (Elf32_Sword)tmp >> 2;
if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){ if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){
printf("BRANCH Overflow\n"); printf("BRANCH Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
*where = (*where & 0xffff0000) | (tmp & 0xffff); *where = (*where & 0xffff0000) | (tmp & 0xffff);
@@ -164,17 +164,18 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default: default:
rtems_rtl_set_error (EINVAL, "rela type record not supported"); rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n"); printf("Unsupported reloc types\n");
return false; return rtems_rtl_elf_rel_failure;
} }
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info)); printf("rela relocation type is %ld\n", ELF_R_TYPE(rela->r_info));
printf("relocated address 0x%08lx\n", (Elf_Addr)where); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -189,10 +190,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -207,7 +208,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -86,7 +86,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -100,10 +100,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -124,7 +124,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
case R_TYPE(PC8): case R_TYPE(PC8):
tmp = symvalue + rela->r_addend - (Elf_Addr)where; tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_8_check(tmp)) if (overflow_8_check(tmp))
return false; return rtems_rtl_elf_rel_failure;
*(uint8_t *)where = tmp; *(uint8_t *)where = tmp;
@@ -137,7 +137,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
case R_TYPE(PC16): case R_TYPE(PC16):
tmp = symvalue + rela->r_addend - (Elf_Addr)where; tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_16_check(tmp)) if (overflow_16_check(tmp))
return false; return rtems_rtl_elf_rel_failure;
*(uint16_t*)where = tmp; *(uint16_t*)where = tmp;
@@ -196,13 +196,13 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %d " "%s: Unsupported relocation type %d "
"in non-PLT relocations", "in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); 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_rel_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -217,10 +217,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -235,7 +235,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -66,7 +66,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -99,10 +99,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported"); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -116,7 +116,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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 * symbol is STT_SECTION, it must be STB_LOCAL. Thus
* just consider symtype here. * just consider symtype here.
*/ */
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -162,7 +162,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
tmp = symvalue + (int)tmp; tmp = symvalue + (int)tmp;
if ((tmp & 0xffff0000) != 0) { if ((tmp & 0xffff0000) != 0) {
printf("R_MIPS_16 Overflow\n"); printf("R_MIPS_16 Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
*where = (tmp & 0xffff) | (*where & 0xffff0000); *where = (tmp & 0xffff) | (*where & 0xffff0000);
@@ -224,7 +224,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
t = ahl + (int16_t)addend; t = ahl + (int16_t)addend;
tmp = symvalue; tmp = symvalue;
if (tmp == 0) if (tmp == 0)
return false; return rtems_rtl_elf_rel_failure;
addend &= 0xffff0000; addend &= 0xffff0000;
addend |= (uint16_t)(t + tmp); addend |= (uint16_t)(t + tmp);
@@ -254,7 +254,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 2; tmp = (Elf_Sword)tmp >> 2;
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) { if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
printf("R_MIPS_PC16 Overflow\n"); printf("R_MIPS_PC16 Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
*where = (tmp & 0xffff) | (*where & 0xffff0000); *where = (tmp & 0xffff) | (*where & 0xffff0000);
@@ -274,10 +274,10 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %ld " "%s: Unsupported relocation type %ld "
"in non-PLT relocations", "in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); 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 bool

View File

@@ -67,7 +67,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -122,7 +122,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 1; tmp = (Elf_Sword)tmp >> 1;
if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){ if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){
printf("Overflow for PCREL10: %ld exceed -0x200:0x1ff\n", tmp); 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); *(uint16_t *)where = (*(uint16_t *)where & 0xfc00) | (tmp & 0x3ff);
@@ -136,13 +136,13 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default: default:
rtems_rtl_set_error (EINVAL, "rela type record not supported"); rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("Unsupported reloc types\n"); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -157,10 +157,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -175,7 +175,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -213,7 +213,14 @@ get_veneer_size (int type)
return rtems_rtl_elf_relocate_tramp_max_size (); 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, rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -226,6 +233,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
Elf_Word tmp; Elf_Word tmp;
uint32_t mask = 0; uint32_t mask = 0;
uint32_t bits = 0; uint32_t bits = 0;
bool needs_tramp = false;
where = (Elf_Addr *)(sect->base + rela->r_offset); where = (Elf_Addr *)(sect->base + rela->r_offset);
switch (ELF_R_TYPE(rela->r_info)) { switch (ELF_R_TYPE(rela->r_info)) {
@@ -259,14 +267,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 24; bits = 24;
mask = 0x3fffffc; 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; tmp = (symvalue + rela->r_addend) >> 2;
if (tmp > ((1<<bits) - 1 )) { if (tmp > ((1<<bits) - 1 )) {
Elf_Word tramp_addr; Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info)); size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) { if (parsing) {
obj->tramp_size += tramp_size; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
return true; 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; tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk, obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend); symvalue + rela->r_addend);
@@ -283,7 +306,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) { if (!parsing) {
*where = tmp; *where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) 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)); (void *)*where, where, rtems_rtl_obj_oname (obj));
} }
break; break;
@@ -341,15 +365,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 14; 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; tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) || if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
((Elf_Sword)tmp < -(1<<(bits-1)))) { ((Elf_Sword)tmp < -(1<<(bits-1)))) {
Elf_Word tramp_addr; Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info)); size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) { if (parsing) {
obj->tramp_size += tramp_size; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
return true; 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; tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk, obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend); symvalue + rela->r_addend);
@@ -367,7 +405,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) { if (!parsing) {
*where = tmp; *where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) 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)); (void *)*where, where, rtems_rtl_obj_oname (obj));
} }
break; break;
@@ -412,12 +451,12 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRId32 "%s: Unsupported relocation type %" PRId32
"in non-PLT relocations", "in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info)); 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, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -434,7 +473,7 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
true); true);
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -451,7 +490,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
false); false);
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -466,10 +505,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -484,7 +523,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -185,7 +185,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -199,10 +199,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, 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); type = ELF_R_TYPE(rela->r_info);
if (type == R_TYPE(NONE)) if (type == R_TYPE(NONE))
return true; return rtems_rtl_elf_rel_no_error;
/* We do JMP_SLOTs in _rtld_bind() below */ /* We do JMP_SLOTs in _rtld_bind() below */
if (type == R_TYPE(JMP_SLOT)) if (type == R_TYPE(JMP_SLOT))
return true; return rtems_rtl_elf_rel_no_error;
/* COPY relocs are also handled elsewhere */ /* COPY relocs are also handled elsewhere */
if (type == R_TYPE(COPY)) if (type == R_TYPE(COPY))
return true; return rtems_rtl_elf_rel_no_error;
/* /*
* We use the fact that relocation types are an `enum' * We use the fact that relocation types are an `enum'
* Note: R_SPARC_6 is currently numerically largest. * Note: R_SPARC_6 is currently numerically largest.
*/ */
if (type > R_TYPE(6)) if (type > R_TYPE(6))
return false; return rtems_rtl_elf_rel_failure;
value = rela->r_addend; 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)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc relative in %s --> %p", printf ("rtl: reloc relative in %s --> %p",
rtems_rtl_obj_oname (obj), (void *)*where); rtems_rtl_obj_oname (obj), (void *)*where);
return true; return rtems_rtl_elf_rel_no_error;
} }
if (RELOC_RESOLVE_SYMBOL (type)) { 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)], reloc_names[ELF_R_TYPE(rela->r_info)],
(void *)tmp, where, rtems_rtl_obj_oname (obj)); (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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -333,10 +333,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -351,7 +351,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
printf ("rtl: rel type record not supported; please report\n"); printf ("rtl: rel type record not supported; please report\n");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -67,7 +67,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0; return 0;
} }
bool rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj, rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -81,10 +81,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname; (void) symname;
(void) syminfo; (void) syminfo;
(void) symvalue; (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, rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela, const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect, 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; tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) { if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) {
printf("Overflow\n"); printf("Overflow\n");
return false; return rtems_rtl_elf_rel_failure;
} }
((uint16_t *)where)[0] = (*(uint16_t *)where & 0xffc0) | ((uint16_t *)where)[0] = (*(uint16_t *)where & 0xffc0) |
@@ -145,13 +145,13 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
default: default:
rtems_rtl_set_error (EINVAL, "rela type record not supported"); rtems_rtl_set_error (EINVAL, "rela type record not supported");
printf("error reloc type\n"); 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, rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -166,10 +166,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); 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, rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel, const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect, const rtems_rtl_obj_sect* sect,
@@ -184,7 +184,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo; (void) syminfo;
(void) symvalue; (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported"); rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false; return rtems_rtl_elf_rel_failure;
} }
bool bool

View File

@@ -583,10 +583,10 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
bool bool
rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj) rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
{ {
if (obj->tramp_size == 0) if (obj->tramps_size == 0)
return true; return true;
obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
obj->tramp_size, obj->tramps_size,
true); true);
if (obj->trampoline == NULL) if (obj->trampoline == NULL)
rtems_rtl_set_error (ENOMEM, "no memory for the trampoline"); 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) if (obj->trampoline != NULL)
{ {
rtems_cache_instruction_sync_after_code_change(obj->trampoline, 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 static void
rtems_rtl_obj_sections_loader (uint32_t mask, rtems_rtl_obj_sections_locate (uint32_t mask,
rtems_rtl_alloc_tag tag, rtems_rtl_alloc_tag tag,
rtems_rtl_obj* obj, rtems_rtl_obj* obj,
int fd, uint8_t* base)
uint8_t* base,
rtems_rtl_obj_sect_handler handler,
void* data)
{ {
rtems_chain_control* sections = &obj->sections; rtems_chain_control* sections = &obj->sections;
rtems_chain_node* node = rtems_chain_first (sections); rtems_chain_node* node = rtems_chain_first (sections);
@@ -1013,9 +1010,7 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
int order = 0; int order = 0;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base); printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
rtems_rtl_alloc_wr_enable (tag, base);
while (!rtems_chain_is_tail (sections, node)) 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)) 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", " a:%" PRIu32 " l:%02d)\n",
order, sect->name, sect->base, sect->size, order, sect->name, sect->base, sect->size,
sect->flags, sect->alignment, sect->link); 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) if (sect->base)
base_offset += sect->size; base_offset += sect->size;
@@ -1070,10 +1044,6 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
node = rtems_chain_next (node); node = rtems_chain_next (node);
} }
rtems_rtl_alloc_wr_disable (tag, base);
return true;
} }
bool 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_DATA, obj);
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, 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; return true;
} }

View File

@@ -143,6 +143,7 @@ typedef struct
bool memory_map; /**< Print the memory map. */ bool memory_map; /**< Print the memory map. */
bool symbols; /**< Print the global symbols. */ bool symbols; /**< Print the global symbols. */
bool dependencies; /**< Print any dependencies. */ bool dependencies; /**< Print any dependencies. */
bool trampolines; /**< Print trampoline stats. */
bool base; /**< Include the base object file. */ bool base; /**< Include the base object file. */
const char* re_name; /**< Name regx to filter on. */ const char* re_name; /**< Name regx to filter on. */
const char* re_symbol; /**< Symbol 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, "%-*cunresolved : %zu\n", indent, ' ', obj->unresolved);
rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users); rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users);
rtems_printf (print->printer, "%-*creferences : %zu\n", indent, ' ', obj->refs); 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, "%-*csymbols : %zi\n", indent, ' ', obj->global_syms);
rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size); 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) if (!dd.first)
rtems_printf (print->printer, "\n"); 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; return true;
} }
@@ -567,18 +597,31 @@ int
rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[]) rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
{ {
rtems_rtl_obj_print print = { 0 }; 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; return 1;
print.printer = printer; print.printer = printer;
print.indent = 1; print.indent = 1;
print.oname = true; print.oname = true;
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.names = rtems_rtl_parse_opt ('n', argc, argv);
print.stats = rtems_rtl_parse_opt ('l', argc, argv);; print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);; print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
print.symbols = rtems_rtl_parse_opt ('s', argc, argv); print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
print.dependencies = rtems_rtl_parse_opt ('d', 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.base = rtems_rtl_parse_opt ('b', argc, argv);;
print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv); print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
}
print.re_symbol = NULL; print.re_symbol = NULL;
print.rtl = rtems_rtl_lock (); print.rtl = rtems_rtl_lock ();
if (print.rtl == NULL) if (print.rtl == NULL)

View File

@@ -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

View File

@@ -27,6 +27,7 @@
#include "rtl-error.h" #include "rtl-error.h"
#include <rtems/rtl/rtl-unresolved.h> #include <rtems/rtl/rtl-unresolved.h>
#include <rtems/rtl/rtl-trace.h> #include <rtems/rtl/rtl-trace.h>
#include "rtl-trampoline.h"
static rtems_rtl_unresolv_block* static rtems_rtl_unresolv_block*
rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved) rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
@@ -101,6 +102,7 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
break; break;
case rtems_rtl_unresolved_reloc: case rtems_rtl_unresolved_reloc:
case rtems_rtl_trampoline_reloc:
++rec; ++rec;
break; break;
} }
@@ -403,6 +405,25 @@ rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
memset (&block->rec[block->recs], 0, bytes); 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 static void
rtems_rtl_unresolved_compact (void) rtems_rtl_unresolved_compact (void)
{ {
@@ -456,19 +477,8 @@ rtems_rtl_unresolved_compact (void)
rec = rtems_rtl_unresolved_rec_next (rec); rec = rtems_rtl_unresolved_rec_next (rec);
} }
if (block->recs == 0) node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
{ block);
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);
}
} }
} }
} }
@@ -480,7 +490,7 @@ rtems_rtl_unresolved_table_open (rtems_rtl_unresolved* unresolved,
unresolved->marker = 0xdeadf00d; unresolved->marker = 0xdeadf00d;
unresolved->block_recs = block_recs; unresolved->block_recs = block_recs;
rtems_chain_initialize_empty (&unresolved->blocks); rtems_chain_initialize_empty (&unresolved->blocks);
return true; return rtems_rtl_unresolved_block_alloc (unresolved);
} }
void void
@@ -632,13 +642,13 @@ rtems_rtl_unresolved_resolve (void)
/* /*
* The resolving process is two separate stages, The first stage is to * The resolving process is two separate stages, The first stage is to
* iterate over the unresolved symbols search the global symbol table. If a * iterate over the unresolved symbols searching the global symbol table. If
* symbol is found iterate over the unresolved relocation records for the * a symbol is found iterate over the unresolved relocation records for the
* symbol fixing up the relocations. The second stage is to search 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 * archives for symbols we have not searched before and if a symbol is found
* found in an archve loaded the object file. Loading an object file stops * in an archve load the object file. Loading an object file stops the
* the search of the archives for symbols and stage one is performed * search of the archives for symbols and stage one is performed again. The
* again. The process repeats until no more symbols are resolved. * process repeats until no more symbols are resolved or there is an error.
*/ */
while (resolving) while (resolving)
{ {
@@ -665,18 +675,87 @@ rtems_rtl_unresolved_resolve (void)
} }
bool bool
rtems_rtl_unresolved_remove (rtems_rtl_obj* obj, rtems_rtl_trampoline_add (rtems_rtl_obj* obj,
const char* name, const uint16_t flags,
const uint16_t sect, const uint16_t sect,
const rtems_rtl_word symvalue,
const rtems_rtl_word* rel) 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 (); unresolved = rtems_rtl_unresolved_unprotected ();
if (unresolved == NULL) if (!unresolved)
return false; 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; 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. * 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); rec->rec.name.length);
break; break;
case rtems_rtl_unresolved_reloc: case rtems_rtl_unresolved_reloc:
case rtems_rtl_trampoline_reloc:
if (dd->show_relocs) 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, dd->rec,
rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname, rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
rec->rec.reloc.name, rec->rec.reloc.name,

View File

@@ -477,6 +477,8 @@ rtems_rtl_find_obj (const char* name)
rtems_rtl_obj* rtems_rtl_obj*
rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym) rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
{ {
if (sym != NULL)
{
rtems_chain_node* node = rtems_chain_first (&rtl->objects); rtems_chain_node* node = rtems_chain_first (&rtl->objects);
while (!rtems_chain_is_tail (&rtl->objects, node)) while (!rtems_chain_is_tail (&rtl->objects, node))
{ {
@@ -493,6 +495,7 @@ rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
return obj; return obj;
node = rtems_chain_next (node); node = rtems_chain_next (node);
} }
}
return NULL; return NULL;
} }

View File

@@ -56,7 +56,7 @@ static void Init(rtems_task_argument arg)
exit (1); exit (1);
} }
for (i = 0; i < 100; ++i) for (i = 0; i < 4; ++i)
{ {
printf ("--------------------------------------------------\n"); printf ("--------------------------------------------------\n");
printf (" Run: %d\n", i); printf (" Run: %d\n", i);

View File

@@ -55,6 +55,7 @@ int rtems_main_o1 (void)
printf (DL_NAME ": dl01_const1: %4zu: %p: %d\n", PAINT_VAR (dl01_const1)); printf (DL_NAME ": dl01_const1: %4zu: %p: %d\n", PAINT_VAR (dl01_const1));
printf (DL_NAME ": dl01_const2: %4zu: %p: %f\n", PAINT_VAR (dl01_const2)); printf (DL_NAME ": dl01_const2: %4zu: %p: %f\n", PAINT_VAR (dl01_const2));
printf (DL_NAME ": dl01_func1: %4zu: %p\n", sizeof(dl01_func1), &dl01_func1); printf (DL_NAME ": dl01_func1: %4zu: %p\n", sizeof(dl01_func1), &dl01_func1);
printf (DL_NAME ": rtems_main_o2: %p\n", &rtems_main_o2);
rtems_main_o2 (); rtems_main_o2 ();

View File

@@ -18,6 +18,6 @@ directives:
concepts: concepts:
+ Load modules with a space between then so short address range relative + Load modules with a space between them so short address range relative
instructions require trampolines. instructions require trampolines.
+ Repeat 100 times. + Repeat 100 times.

View File

@@ -56,7 +56,7 @@ static void Init(rtems_task_argument arg)
exit (1); exit (1);
} }
for (i = 0; i < 100; ++i) for (i = 0; i < 4; ++i)
{ {
printf ("--------------------------------------------------\n"); printf ("--------------------------------------------------\n");
printf (" Run: %d\n", i); printf (" Run: %d\n", i);