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

@@ -207,7 +207,7 @@ struct rtems_rtl_obj
size_t text_size; /**< The size of the text section. */
void* const_base; /**< The base address of the const section
* in memory. */
size_t const_size; /**< The size of the const section. */
size_t const_size; /**< The size of the const section. */
void* eh_base; /**< The base address of the eh section in
* memory. */
size_t eh_size; /**< The size of the eh section. */
@@ -227,10 +227,14 @@ struct rtems_rtl_obj
* obj. */
void* trampoline; /**< Trampoline memory. Used for fixups or
* 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
* relocators can take memory from the
* 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. */
void* loader; /**< The file details specific to a
* 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.
* @retval bool Returns @true if the space is available.
*/
static inline bool rtems_rtl_obj_has_ramp_space (const rtems_rtl_obj* obj,
const size_t size)
static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj,
const size_t size)
{
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
* 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_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;
/**
@@ -101,7 +102,7 @@ typedef struct rtems_rtl_unresolv_symbol
/**
* Unresolved externals symbols require the relocation records to be held
* and references.
* and referenced.
*/
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_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.
*/
@@ -121,7 +134,8 @@ typedef struct rtems_rtl_unresolv_rec
union
{
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;
} rtems_rtl_unresolv_rec;

View File

@@ -72,7 +72,7 @@ extern "C" {
/**
* 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.

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 ();
if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
printf ("rtl: alloc: wr-enable: addr=%p\n", address);
printf ("rtl: alloc: wr-disable: addr=%p\n", address);
if (rtl != NULL && address != NULL)
rtl->allocator.allocator (RTEMS_RTL_ALLOC_WR_DISABLE,

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
* found in the file LICENSE in this distribution or at
@@ -31,11 +31,12 @@
#include "rtl-elf.h"
#include "rtl-error.h"
#include <rtems/rtl/rtl-trace.h>
#include "rtl-trampoline.h"
#include "rtl-unwind.h"
#include <rtems/rtl/rtl-unresolved.h>
/**
* The offsets in the unresolved array.
* The offsets in the reloc words.
*/
#define REL_R_OFFSET (0)
#define REL_R_INFO (1)
@@ -166,66 +167,77 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
void* data)
{
rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
rtems_rtl_word rel_words[3];
rtems_rtl_elf_rel_status rs;
/*
* The symbol has to have been resolved to parse the reloc record. Unresolved
* symbols are handled in the relocator but we need to count them here so a
* trampoline is accounted for. We have to assume the unresolved may be out of
* of range.
* Check the reloc record to see if a trampoline is needed.
*/
if (!resolved)
if (is_rela)
{
++rd->unresolved;
const Elf_Rela* rela = (const Elf_Rela*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rela tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend);
rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
symname, sym->st_info, symvalue);
rel_words[REL_R_OFFSET] = rela->r_offset;
rel_words[REL_R_INFO] = rela->r_info;
rel_words[REL_R_ADDEND] = rela->r_addend;
}
else
{
/*
* Check the reloc record to see if a trampoline is needed.
*/
if (is_rela)
{
const Elf_Rela* rela = (const Elf_Rela*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rela tramp: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend);
if (!rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
symname, sym->st_info, symvalue))
return false;
}
else
{
const Elf_Rel* rel = (const Elf_Rel*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rel tramp: sym:%s(%d)=%08jx type:%d off:%08jx\n",
symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset);
if (!rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
symname, sym->st_info, symvalue))
return false;
}
const Elf_Rel* rel = (const Elf_Rel*) relbuf;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n",
ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset);
rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
symname, sym->st_info, symvalue);
rel_words[REL_R_OFFSET] = rel->r_offset;
rel_words[REL_R_INFO] = rel->r_info;
rel_words[REL_R_ADDEND] = 0;
}
if (symname != NULL)
if (rs == rtems_rtl_elf_rel_failure)
return false;
if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add)
{
uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8);
if (!rtems_rtl_trampoline_add (obj, flags,
targetsect->section, symvalue, rel_words))
return false;
}
/*
* Handle any dependencies if there is a valid symbol.
*/
if (symname != NULL)
{
/*
* Find the symbol's object file. It cannot be NULL so ignore that result
* if returned, it means something is corrupted. We are in an iterator.
*/
rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
if (sobj != NULL)
{
/*
* Find the symbol's object file. It cannot be NULL so ignore that result
* if returned, it means something is corrupted. We are in an iterator.
* A dependency is not the base kernel image or itself. Tag the object as
* having been visited so we count it only once.
*/
rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol);
if (sobj != NULL)
if (sobj != rtems_rtl_baseimage () && obj != sobj &&
(sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
{
/*
* A dependency is not the base kernel image or itself. Tag the object as
* having been visited so we count it only once.
*/
if (sobj != rtems_rtl_baseimage () && obj != sobj &&
(sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
{
sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
++rd->dependents;
}
sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
++rd->dependents;
}
}
}
@@ -278,7 +290,8 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
}
else
{
rtems_rtl_obj* sobj;
rtems_rtl_obj* sobj;
rtems_rtl_elf_rel_status rs;
if (is_rela)
{
@@ -287,8 +300,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rela->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
(uintmax_t) rela->r_offset, (int) rela->r_addend);
if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
symname, sym->st_info, symvalue))
rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
symname, sym->st_info, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
else
@@ -298,8 +312,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj,
symname, (int) ELF_R_SYM (rel->r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
(uintmax_t) rel->r_offset);
if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
symname, sym->st_info, symvalue))
rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
symname, sym->st_info, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
@@ -419,7 +434,10 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj,
/*
* Only need the name of the symbol if global or a common symbol.
*/
if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT ||
ELF_ST_TYPE (sym.st_info) == STT_COMMON ||
ELF_ST_TYPE (sym.st_info) == STT_FUNC ||
ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
ELF_ST_TYPE (sym.st_info) == STT_TLS ||
sym.st_shndx == SHN_COMMON)
{
@@ -491,10 +509,11 @@ bool
rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
rtems_rtl_obj_sym* sym)
{
rtems_rtl_obj_sect* sect;
bool is_rela;
Elf_Word symvalue;
rtems_rtl_obj* sobj;
rtems_rtl_obj_sect* sect;
bool is_rela;
Elf_Word symvalue;
rtems_rtl_obj* sobj;
rtems_rtl_elf_rel_status rs;
is_rela = reloc->flags & 1;
@@ -516,8 +535,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n",
(int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
(uintmax_t) rela.r_offset, (int) rela.r_addend);
if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
sym->name, sym->data, symvalue))
rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
sym->name, sym->data, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
else
@@ -529,8 +549,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
printf ("rtl: rel: sym:%d type:%d off:%08jx\n",
(int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
(uintmax_t) rel.r_offset);
if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
sym->name, sym->data, symvalue))
rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
sym->name, sym->data, symvalue);
if (rs != rtems_rtl_elf_rel_no_error)
return false;
}
@@ -621,16 +642,117 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
return true;
}
/**
* Struct to handle trampoline reloc recs in the unresolved table.
*/
typedef struct rtems_rtl_tramp_data
{
bool failure;
rtems_rtl_obj* obj;
size_t count;
size_t total;
} rtems_rtl_tramp_data;
static bool
rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
void* data)
{
rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data;
if (rec->type == rtems_rtl_trampoline_reloc)
{
const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp;
++td->total;
if (tramp->obj == td->obj)
{
const rtems_rtl_obj_sect* targetsect;
Elf_Byte st_info;
Elf_Word symvalue;
rtems_rtl_elf_rel_status rs;
bool* failure = (bool*) data;
const bool is_rela = (tramp->flags & 1) == 1;
const bool unresolved = (tramp->flags & (1 << 1)) != 0;
++td->count;
targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect);
st_info = tramp->flags >> 8;
symvalue = tramp->symvalue;
if (is_rela)
{
Elf_Rela rela = {
.r_offset = tramp->rel[REL_R_OFFSET],
.r_info = tramp->rel[REL_R_INFO],
.r_addend = tramp->rel[REL_R_ADDEND]
};
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n",
ELF_ST_BIND (st_info) == STB_GLOBAL ||
ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
(int) ELF_R_SYM (rela.r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rela.r_info),
(uintmax_t) rela.r_offset, (int) rela.r_addend);
rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect,
NULL, st_info, symvalue);
}
else
{
Elf_Rel rel = {
.r_offset = tramp->rel[REL_R_OFFSET],
.r_info = tramp->rel[REL_R_INFO],
};
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n",
ELF_ST_BIND (st_info) == STB_GLOBAL ||
ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
(int) ELF_R_SYM (rel.r_info),
(uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info),
(uintmax_t) rel.r_offset);
rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect,
NULL, st_info, symvalue);
}
if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
tramp->obj->tramps_size += tramp->obj->tramp_size;
if (rs == rtems_rtl_elf_rel_failure)
{
*failure = true;
return true;
}
}
}
return false;
}
static bool
rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
{
rtems_rtl_tramp_data td = { 0 };
td.obj = obj;
/*
* See which relocs are out of range and need a trampoline.
*/
rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td);
if (td.failure)
return false;
rtems_rtl_trampoline_remove (obj);
obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n",
obj->tramp_relocs, td.count, td.total);
/*
* Add on enough space to handle the unresolved externals that need to be
* resolved at some point in time. They could all require fixups and
* trampolines.
*/
obj->tramp_size +=
rtems_rtl_elf_relocate_tramp_max_size () * unresolved;
obj->tramps_size += obj->tramp_size * unresolved;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: tramp:elf: slots: %zu (%zu)\n",
obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size,
obj->tramps_size);
return rtems_rtl_obj_alloc_trampoline (obj);
}
@@ -653,10 +775,10 @@ rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
}
static bool
rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
int fd,
rtems_rtl_obj_sect* sect,
void* data)
rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj,
int fd,
rtems_rtl_obj_sect* sect,
void* data)
{
rtems_rtl_obj_cache* symbols;
rtems_rtl_obj_cache* strings;
@@ -720,19 +842,20 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
* we need to make sure there is a valid seciton.
*/
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \
"type:%-2d sect:%d size:%d\n",
printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d " \
"type:%-2d sect:%-5d size:%-5d value:%d\n",
sym, (int) symbol.st_name, name,
(int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info),
symbol.st_shndx,
(int) symbol.st_size);
(int) symbol.st_size,
(int) symbol.st_value);
/*
* If a duplicate forget it.
*/
if (rtems_rtl_symbol_global_find (name))
continue;
/*
* If a duplicate forget it.
*/
if (rtems_rtl_symbol_global_find (name))
continue;
if ((symbol.st_shndx != 0) &&
((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
@@ -775,7 +898,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
else
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n",
printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n",
sym, (int) symbol.st_name, name);
++globals;
global_string_space += strlen (name) + 1;
@@ -784,7 +907,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n",
printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n",
sym, (int) symbol.st_name, name);
++locals;
local_string_space += strlen (name) + 1;
@@ -849,14 +972,14 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off,
&symbol, sizeof (symbol)))
{
if (locals)
if (obj->local_syms)
{
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
obj->local_table = NULL;
obj->local_size = 0;
obj->local_syms = 0;
}
if (globals)
if (obj->global_syms)
{
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
obj->global_table = NULL;
@@ -875,78 +998,113 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj,
(ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
(ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
{
rtems_rtl_obj_sect* symsect;
rtems_rtl_obj_sym* osym;
char* string;
Elf_Word value;
rtems_rtl_obj_sym* osym;
char* string;
Elf_Word value;
const char* name;
symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
if (symsect)
off = obj->ooffset + strtab->offset + symbol.st_name;
len = RTEMS_RTL_ELF_STRING_MAX;
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
return false;
/*
* If a duplicate forget it.
*/
if (rtems_rtl_symbol_global_find (name))
continue;
if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
(ELF_ST_BIND (symbol.st_info) == STB_WEAK))
{
const char* name;
off = obj->ooffset + strtab->offset + symbol.st_name;
len = RTEMS_RTL_ELF_STRING_MAX;
if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
return false;
/*
* If a duplicate forget it.
*/
if (rtems_rtl_symbol_global_find (name))
continue;
if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
(ELF_ST_BIND (symbol.st_info) == STB_WEAK))
{
osym = gsym;
string = gstring;
gstring += strlen (name) + 1;
++gsym;
}
else
{
osym = lsym;
string = lstring;
lstring += strlen (name) + 1;
++lsym;
}
/*
* Allocate any common symbols in the common section.
*/
if (symbol.st_shndx == SHN_COMMON)
{
size_t value_off = rtems_rtl_obj_align (common_offset,
symbol.st_value);
common_offset = value_off + symbol.st_size;
value = value_off;
}
else
{
value = symbol.st_value;
}
rtems_chain_set_off_chain (&osym->node);
memcpy (string, name, strlen (name) + 1);
osym->name = string;
osym->value = value + (uint8_t*) symsect->base;
osym->data = symbol.st_info;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \
"type:%-2d val:%8p sect:%d size:%d\n",
sym, (int) symbol.st_name, osym->name,
(int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info),
osym->value, symbol.st_shndx,
(int) symbol.st_size);
osym = gsym;
string = gstring;
gstring += strlen (name) + 1;
++gsym;
}
else
{
osym = lsym;
string = lstring;
lstring += strlen (name) + 1;
++lsym;
}
/*
* Allocate any common symbols in the common section.
*/
if (symbol.st_shndx == SHN_COMMON)
{
size_t value_off = rtems_rtl_obj_align (common_offset,
symbol.st_value);
common_offset = value_off + symbol.st_size;
value = value_off;
}
else
{
value = symbol.st_value;
}
rtems_chain_set_off_chain (&osym->node);
memcpy (string, name, strlen (name) + 1);
osym->name = string;
osym->value = (uint8_t*) value;
osym->data = symbol.st_shndx;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
"type:%-2d val:%-8p sect:%-3d size:%d\n",
sym, (int) symbol.st_name, osym->name,
(int) ELF_ST_BIND (symbol.st_info),
(int) ELF_ST_TYPE (symbol.st_info),
osym->value, symbol.st_shndx,
(int) symbol.st_size);
}
}
if (globals)
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);
}
}
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);
return true;
@@ -1434,6 +1592,11 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
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
* 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;
/*
* See if there are any common variables and if there are add a common
* section.
* Set the entry point if there is one.
*/
obj->entry = (void*)(uintptr_t) ehdr.e_entry;
/*
* Load the symbol table.
*
* 1. See if there are any common variables and if there are add a
* common section.
* 2. Add up the common.
* 3.
*/
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
return false;
if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
return false;
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &ehdr))
return false;
/*
* Set the entry point if there is one.
* Parse the relocation records. It lets us know how many dependents
* and fixup trampolines there are.
*/
obj->entry = (void*)(uintptr_t) ehdr.e_entry;
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
return false;
/*
* Lock the allocator so the section memory and the trampoline memory are as
@@ -1468,17 +1644,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr))
return false;
/*
* Load the sections and symbols and then relocation to the base address.
*/
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
/*
* Parse the relocation records. It lets us know how many dependents
* and fixup trampolines there are.
*/
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
return false;
if (!rtems_rtl_elf_dependents (obj, &relocs))
@@ -1492,9 +1658,15 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
*/
rtems_rtl_alloc_unlock ();
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
/*
* Load the sections and symbols and then relocation to the base address.
*/
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
/*
* Fix up the relocations.
*/
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
return false;

View File

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

View File

@@ -147,7 +147,7 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -162,10 +162,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -180,10 +180,10 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
static bool
static rtems_rtl_elf_rel_status
rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -209,24 +209,37 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(CALL): /* BL/BLX */
case R_TYPE(JUMP24): /* B/BL<cond> */
insn = *where;
if (parsing)
{
addend = 0;
}
else
{
insn = *where;
if (insn & 0x00800000)
addend = insn | 0xff000000;
else addend = insn & 0x00ffffff;
if (insn & 0x00800000)
addend = insn | 0xff000000;
else addend = insn & 0x00ffffff;
if (isThumb(symvalue)) {
if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
else {
if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
*where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
} else {
printf("JUMP24 is not suppored from arm to thumb\n");
return false;
if (isThumb(symvalue)) {
if ((insn & 0xfe000000) == 0xfa000000); /* Already blx */
else {
if ((insn & 0xff000000) == 0xeb000000) { /* BL <label> */
*where = (insn & 0x00ffffff) | 0xfa000000; /* BL-->BLX */
} else {
printf("JUMP24 is not suppored from arm to thumb\n");
return rtems_rtl_elf_rel_failure;
}
}
}
}
if (parsing && sect->base == 0) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: JUMP24/PC24/CALL tramp cache\n");
return rtems_rtl_elf_rel_tramp_cache;
}
tmp = symvalue + (addend << 2) - (Elf_Addr)where;
tmp = (Elf_Sword)tmp >> 2;
@@ -235,15 +248,16 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) {
obj->tramp_size += tramp_size;
return true;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: JUMP24/PC24/CALL tramp add\n");
return rtems_rtl_elf_rel_tramp_add;
}
if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
rtems_rtl_set_error (EINVAL,
"%s: CALL/JUMP24: overflow: no tramp memory",
sect->name);
return false;
return rtems_rtl_elf_rel_failure;
}
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
@@ -286,7 +300,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 16;
if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
printf("MOVT_ABS Overflow\n");
return false;
return rtems_rtl_elf_rel_failure;
}
}
@@ -367,13 +381,22 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
case R_TYPE(THM_JUMP24):
/* same as THM_PC22; insn b.w */
case R_TYPE(THM_PC22):
upper_insn = *(uint16_t *)where;
lower_insn = *((uint16_t *)where + 1);
sign = (upper_insn & (1 << 10)) >> 10;
i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
if (parsing)
{
addend = 0;
upper_insn = 0;
lower_insn = 0;
}
else
{
upper_insn = *(uint16_t *)where;
lower_insn = *((uint16_t *)where + 1);
sign = (upper_insn & (1 << 10)) >> 10;
i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
}
if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
else {
@@ -381,32 +404,40 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
#if !ALLOW_UNTESTED_RELOCS
printf("THM_JUMP24 to arm not supported\n");
return false;
return rtems_rtl_elf_rel_failure;
#endif
}
else {
/* THM_CALL bl-->blx */
lower_insn &=~(1<<12);
lower_insn &= ~(1<<12);
}
}
if (parsing && sect->base == 0) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: THM_CALL/JUMP24 tramp cache\n");
return rtems_rtl_elf_rel_tramp_cache;
}
tmp = symvalue + addend;
tmp = tmp - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
if (parsing) {
obj->tramp_size += tramp_size;
return true;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: THM_CALL/JUMP24 tramp add: %08x - %p = %i\n",
symvalue + addend, where, (Elf_Sword) tmp);
return rtems_rtl_elf_rel_tramp_add;
}
if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
rtems_rtl_set_error (EINVAL,
"%s: THM_CALL/JUMP24: overflow: no tramp memory",
sect->name);
return false;
return rtems_rtl_elf_rel_failure;
}
tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
@@ -438,7 +469,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
if (!isThumb(symvalue)) {
printf("THM_JUMP19 to arm not supported\n");
return false;
return rtems_rtl_elf_rel_failure;
}
upper_insn = *(uint16_t *)where;
@@ -463,8 +494,7 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
rtems_rtl_set_error (EINVAL, "%s: Overflow %" PRIu32 " "
"THM_JUMP19 relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return true;
return false;
return rtems_rtl_elf_rel_failure;
}
sign = (tmp >> 20) & 0x1;
@@ -511,13 +541,13 @@ rtems_rtl_elf_reloc_rel (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return false;
return rtems_rtl_elf_rel_failure;
}
return true;
return rtems_rtl_elf_rel_no_error;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -534,7 +564,7 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
true);
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,

View File

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

View File

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

View File

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

View File

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

View File

@@ -86,7 +86,7 @@ rtems_rtl_elf_relocate_tramp_max_size (void)
return 0;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -100,10 +100,10 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
(void) symname;
(void) syminfo;
(void) symvalue;
return true;
return rtems_rtl_elf_rel_no_error;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -118,91 +118,91 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
where = (Elf_Addr *)(sect->base + rela->r_offset);
switch (ELF_R_TYPE(rela->r_info)) {
case R_TYPE(NONE):
break;
case R_TYPE(NONE):
break;
case R_TYPE(PC8):
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_8_check(tmp))
return false;
case R_TYPE(PC8):
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_8_check(tmp))
return rtems_rtl_elf_rel_failure;
*(uint8_t *)where = tmp;
*(uint8_t *)where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
case R_TYPE(PC16):
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_16_check(tmp))
return false;
case R_TYPE(PC16):
tmp = symvalue + rela->r_addend - (Elf_Addr)where;
if (overflow_16_check(tmp))
return rtems_rtl_elf_rel_failure;
*(uint16_t*)where = tmp;
*(uint16_t*)where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
case R_TYPE(PC32):
target = (Elf_Addr) symvalue + rela->r_addend;
*where += target - (Elf_Addr)where;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
case R_TYPE(PC32):
target = (Elf_Addr) symvalue + rela->r_addend;
*where += target - (Elf_Addr)where;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
sect->name, (void*) (symvalue + rela->r_addend),
(void *)*where, rtems_rtl_obj_oname (obj));
break;
case R_TYPE(GOT32):
case R_TYPE(32):
case R_TYPE(GLOB_DAT):
target = (Elf_Addr) symvalue + rela->r_addend;
case R_TYPE(GOT32):
case R_TYPE(32):
case R_TYPE(GLOB_DAT):
target = (Elf_Addr) symvalue + rela->r_addend;
if (*where != target)
*where = target;
if (*where != target)
*where = target;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
sect->name, (void *)*where,
rtems_rtl_obj_oname (obj));
break;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
sect->name, (void *)*where,
rtems_rtl_obj_oname (obj));
break;
case R_TYPE(RELATIVE):
*where += (Elf_Addr) sect->base + rela->r_addend;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc RELATIVE in %s --> %p\n",
rtems_rtl_obj_oname (obj), (void *)*where);
break;
case R_TYPE(RELATIVE):
*where += (Elf_Addr) sect->base + rela->r_addend;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: reloc RELATIVE in %s --> %p\n",
rtems_rtl_obj_oname (obj), (void *)*where);
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the
* COPY relocation is not in a shared library. They
* are allowed only in executable files.
*/
printf ("rtl: reloc COPY (please report)\n");
break;
case R_TYPE(COPY):
/*
* These are deferred until all other relocations have
* been done. All we do here is make sure that the
* COPY relocation is not in a shared library. They
* are allowed only in executable files.
*/
printf ("rtl: reloc COPY (please report)\n");
break;
default:
printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
"contents = %p\n",
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)*where);
rtems_rtl_set_error (EINVAL,
"%s: Unsupported relocation type %d "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
return false;
default:
printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
"contents = %p\n",
ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
(void *)rela->r_offset, (void *)*where);
rtems_rtl_set_error (EINVAL,
"%s: Unsupported relocation type %d "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
return rtems_rtl_elf_rel_failure;
}
return true;
return rtems_rtl_elf_rel_no_error;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -217,10 +217,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -235,7 +235,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
bool

View File

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

View File

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

View File

@@ -213,7 +213,14 @@ get_veneer_size (int type)
return rtems_rtl_elf_relocate_tramp_max_size ();
}
static bool
/**
* The offsets in the reloc words.
*/
#define REL_R_OFFSET (0)
#define REL_R_INFO (1)
#define REL_R_ADDEND (2)
static rtems_rtl_elf_rel_status
rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -226,6 +233,7 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
Elf_Word tmp;
uint32_t mask = 0;
uint32_t bits = 0;
bool needs_tramp = false;
where = (Elf_Addr *)(sect->base + rela->r_offset);
switch (ELF_R_TYPE(rela->r_info)) {
@@ -259,14 +267,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 24;
mask = 0x3fffffc;
}
if (parsing && sect->base == 0) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: ADDR14/ADDR24 tramp cache\n");
return rtems_rtl_elf_rel_tramp_cache;
}
tmp = (symvalue + rela->r_addend) >> 2;
if (tmp > ((1<<bits) - 1 )) {
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) {
obj->tramp_size += tramp_size;
return true;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: ADDR14/ADDR24 tramp add\n");
return rtems_rtl_elf_rel_tramp_add;
}
if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: ADDR14/ADDR24 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: ADDR14/ADDR24", sect->name);
return rtems_rtl_elf_rel_failure;
}
needs_tramp = true;
tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend);
@@ -283,7 +306,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) {
*where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
printf ("rtl: ADDR14/ADDR24%s %p @ %p in %s\n",
needs_tramp ? "(tramp)" : "",
(void *)*where, where, rtems_rtl_obj_oname (obj));
}
break;
@@ -341,15 +365,29 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
bits = 14;
}
if (parsing && sect->base == 0) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: REL24/REL14 tramp cache\n");
return rtems_rtl_elf_rel_tramp_cache;
}
tmp =((int) (symvalue + rela->r_addend - (Elf_Addr)where)) >> 2;
if (((Elf_Sword)tmp > ((1<<(bits-1)) - 1)) ||
((Elf_Sword)tmp < -(1<<(bits-1)))) {
Elf_Word tramp_addr;
size_t tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
if (parsing) {
obj->tramp_size += tramp_size;
return true;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: REL24/REL14 tramp add\n");
return rtems_rtl_elf_rel_tramp_add;
}
if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: REL24/REL14 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: REL24/REL14", sect->name);
return rtems_rtl_elf_rel_failure;
}
needs_tramp = true;
tramp_addr = (Elf_Addr) obj->tramp_brk;
obj->tramp_brk = set_veneer(obj->tramp_brk,
symvalue + rela->r_addend);
@@ -367,7 +405,8 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
if (!parsing) {
*where = tmp;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
printf ("rtl: REL24/REL14 %p @ %p in %s\n",
printf ("rtl: REL24/REL14%s %p @ %p in %s\n",
needs_tramp ? "(tramp)" : "",
(void *)*where, where, rtems_rtl_obj_oname (obj));
}
break;
@@ -412,12 +451,12 @@ rtems_rtl_elf_reloc_rela (rtems_rtl_obj* obj,
"%s: Unsupported relocation type %" PRId32
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
return false;
return rtems_rtl_elf_rel_failure;
}
return true;
return rtems_rtl_elf_rel_no_error;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -434,7 +473,7 @@ rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj* obj,
true);
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
@@ -451,7 +490,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
false);
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -466,10 +505,10 @@ rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
bool
rtems_rtl_elf_rel_status
rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
@@ -484,7 +523,7 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
(void) syminfo;
(void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
return rtems_rtl_elf_rel_failure;
}
bool

View File

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

View File

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

View File

@@ -583,10 +583,10 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
bool
rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
{
if (obj->tramp_size == 0)
if (obj->tramps_size == 0)
return true;
obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
obj->tramp_size,
obj->tramps_size,
true);
if (obj->trampoline == NULL)
rtems_rtl_set_error (ENOMEM, "no memory for the trampoline");
@@ -903,7 +903,7 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
if (obj->trampoline != NULL)
{
rtems_cache_instruction_sync_after_code_change(obj->trampoline,
obj->tramp_size);
obj->tramps_size);
}
}
@@ -998,14 +998,11 @@ rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj* obj)
}
}
static bool
rtems_rtl_obj_sections_loader (uint32_t mask,
rtems_rtl_alloc_tag tag,
rtems_rtl_obj* obj,
int fd,
uint8_t* base,
rtems_rtl_obj_sect_handler handler,
void* data)
static void
rtems_rtl_obj_sections_locate (uint32_t mask,
rtems_rtl_alloc_tag tag,
rtems_rtl_obj* obj,
uint8_t* base)
{
rtems_chain_control* sections = &obj->sections;
rtems_chain_node* node = rtems_chain_first (sections);
@@ -1013,9 +1010,7 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
int order = 0;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
rtems_rtl_alloc_wr_enable (tag, base);
printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
while (!rtems_chain_is_tail (sections, node))
{
@@ -1032,32 +1027,11 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
}
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
printf ("rtl: locating:%2d: %s -> %p (s:%zi f:%04" PRIx32
" a:%" PRIu32 " l:%02d)\n",
order, sect->name, sect->base, sect->size,
sect->flags, sect->alignment, sect->link);
if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
{
if (!handler (obj, fd, sect, data))
{
sect->base = 0;
rtems_rtl_alloc_wr_disable (tag, base);
return false;
}
}
else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
{
memset (sect->base, 0, sect->size);
}
else
{
/*
* This section is not to be loaded, clear the base.
*/
sect->base = 0;
}
if (sect->base)
base_offset += sect->size;
@@ -1070,10 +1044,6 @@ rtems_rtl_obj_sections_loader (uint32_t mask,
node = rtems_chain_next (node);
}
rtems_rtl_alloc_wr_disable (tag, base);
return true;
}
bool
@@ -1159,6 +1129,94 @@ rtems_rtl_obj_alloc_sections (rtems_rtl_obj* obj,
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA, obj);
rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS, obj);
/*
* Locate all text, data and bss sections in seperate operations so each type of
* section is grouped together.
*/
rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT,
rtems_rtl_alloc_text_tag (),
obj, obj->text_base);
rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST,
rtems_rtl_alloc_const_tag (),
obj, obj->const_base);
rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH,
rtems_rtl_alloc_eh_tag (),
obj, obj->eh_base);
rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA,
rtems_rtl_alloc_data_tag (),
obj, obj->data_base);
rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS,
rtems_rtl_alloc_bss_tag (),
obj, obj->bss_base);
return true;
}
static bool
rtems_rtl_obj_sections_loader (uint32_t mask,
rtems_rtl_alloc_tag tag,
rtems_rtl_obj* obj,
int fd,
uint8_t* base,
rtems_rtl_obj_sect_handler handler,
void* data)
{
rtems_chain_control* sections = &obj->sections;
rtems_chain_node* node = rtems_chain_first (sections);
int order = 0;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading section: mask:%08" PRIx32 " base:%p\n", mask, base);
rtems_rtl_alloc_wr_enable (tag, base);
while (!rtems_chain_is_tail (sections, node))
{
rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
if ((sect->size != 0) && ((sect->flags & mask) == mask))
{
if (sect->load_order == order)
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
" a:%" PRIu32 " l:%02d)\n",
order, sect->name, sect->base, sect->size,
sect->flags, sect->alignment, sect->link);
if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD)
{
if (!handler (obj, fd, sect, data))
{
sect->base = 0;
rtems_rtl_alloc_wr_disable (tag, base);
return false;
}
}
else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO)
{
memset (sect->base, 0, sect->size);
}
else
{
/*
* This section is not to be loaded, clear the base.
*/
sect->base = 0;
}
++order;
node = rtems_chain_first (sections);
continue;
}
}
node = rtems_chain_next (node);
}
rtems_rtl_alloc_wr_disable (tag, base);
return true;
}

View File

@@ -143,6 +143,7 @@ typedef struct
bool memory_map; /**< Print the memory map. */
bool symbols; /**< Print the global symbols. */
bool dependencies; /**< Print any dependencies. */
bool trampolines; /**< Print trampoline stats. */
bool base; /**< Include the base object file. */
const char* re_name; /**< Name regx to filter on. */
const char* re_symbol; /**< Symbol regx to filter on. */
@@ -515,6 +516,8 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
rtems_printf (print->printer, "%-*cunresolved : %zu\n", indent, ' ', obj->unresolved);
rtems_printf (print->printer, "%-*cusers : %zu\n", indent, ' ', obj->users);
rtems_printf (print->printer, "%-*creferences : %zu\n", indent, ' ', obj->refs);
rtems_printf (print->printer, "%-*ctrampolines : %zu\n", indent, ' ',
rtems_rtl_obj_trampolines (obj));
rtems_printf (print->printer, "%-*csymbols : %zi\n", indent, ' ', obj->global_syms);
rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
}
@@ -535,6 +538,33 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
if (!dd.first)
rtems_printf (print->printer, "\n");
}
if (print->trampolines)
{
if (obj->tramp_size == 0)
{
rtems_printf (print->printer, "%-*ctrampolines: not supported\n", indent, ' ');
}
else
{
size_t slots = rtems_rtl_obj_trampoline_slots (obj);
size_t used = rtems_rtl_obj_trampolines (obj);
rtems_printf (print->printer, "%-*ctrampolines:\n", indent, ' ');
rtems_printf (print->printer, "%-*cslots : %zu\n", indent + 4, ' ',
slots);
rtems_printf (print->printer, "%-*csize : %zu\n", indent + 4, ' ',
obj->tramps_size);
rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ',
obj->tramp_size);
rtems_printf (print->printer, "%-*cused : %zu\n", indent + 4, ' ',
used);
rtems_printf (print->printer, "%-*crelocs : %zu\n", indent + 4, ' ',
obj->tramp_relocs);
rtems_printf (print->printer, "%-*cunresolved: %zu\n", indent + 4, ' ',
slots - obj->tramp_relocs);
rtems_printf (print->printer, "%-*cyield : %zu%%\n", indent + 4, ' ',
slots ? (used * 100) / slots : 0);
}
}
return true;
}
@@ -567,18 +597,31 @@ int
rtems_rtl_shell_list (const rtems_printer* printer, int argc, char* argv[])
{
rtems_rtl_obj_print print = { 0 };
if (!rtems_rtl_check_opts (printer, "nlmsdb", argc, argv))
if (!rtems_rtl_check_opts (printer, "anlmsdbt", argc, argv))
return 1;
print.printer = printer;
print.indent = 1;
print.oname = true;
print.names = rtems_rtl_parse_opt ('n', argc, argv);
print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
print.base = rtems_rtl_parse_opt ('b', argc, argv);;
print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
if (rtems_rtl_parse_opt ('a', argc, argv))
{
print.names = true;
print.stats = true;
print.memory_map = true;
print.symbols = true;
print.dependencies = true;
print.trampolines = true;
}
else
{
print.names = rtems_rtl_parse_opt ('n', argc, argv);
print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
print.trampolines = rtems_rtl_parse_opt ('t', argc, argv);;
print.base = rtems_rtl_parse_opt ('b', argc, argv);;
print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
}
print.re_symbol = NULL;
print.rtl = rtems_rtl_lock ();
if (print.rtl == NULL)

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 <rtems/rtl/rtl-unresolved.h>
#include <rtems/rtl/rtl-trace.h>
#include "rtl-trampoline.h"
static rtems_rtl_unresolv_block*
rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
@@ -69,7 +70,7 @@ rtems_rtl_unresolved_symbol_recs (const char* name)
static int
rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
rtems_rtl_unresolv_rec* rec)
rtems_rtl_unresolv_rec* rec)
{
return rec - &block->rec[0];
}
@@ -101,6 +102,7 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
break;
case rtems_rtl_unresolved_reloc:
case rtems_rtl_trampoline_reloc:
++rec;
break;
}
@@ -403,6 +405,25 @@ rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
memset (&block->rec[block->recs], 0, bytes);
}
static rtems_chain_node*
rtems_rtl_unresolved_delete_block_if_empty (rtems_chain_control* blocks,
rtems_rtl_unresolv_block* block)
{
rtems_chain_node* node = &block->link;
rtems_chain_node* next_node = rtems_chain_next (node);
/*
* Always leave a single block allocated. Eases possible heap fragmentation.
*/
if (block->recs == 0 && !rtems_chain_has_only_one_node (blocks))
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: unresolv: block-del %p\n", block);
rtems_chain_extract (node);
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
}
return next_node;
}
static void
rtems_rtl_unresolved_compact (void)
{
@@ -456,19 +477,8 @@ rtems_rtl_unresolved_compact (void)
rec = rtems_rtl_unresolved_rec_next (rec);
}
if (block->recs == 0)
{
rtems_chain_node* next_node = rtems_chain_next (node);
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: unresolv: block-del %p\n", block);
rtems_chain_extract (node);
rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
node = next_node;
}
else
{
node = rtems_chain_next (node);
}
node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
block);
}
}
}
@@ -480,7 +490,7 @@ rtems_rtl_unresolved_table_open (rtems_rtl_unresolved* unresolved,
unresolved->marker = 0xdeadf00d;
unresolved->block_recs = block_recs;
rtems_chain_initialize_empty (&unresolved->blocks);
return true;
return rtems_rtl_unresolved_block_alloc (unresolved);
}
void
@@ -632,13 +642,13 @@ rtems_rtl_unresolved_resolve (void)
/*
* The resolving process is two separate stages, The first stage is to
* iterate over the unresolved symbols search the global symbol table. If a
* symbol is found iterate over the unresolved relocation records for the
* iterate over the unresolved symbols searching the global symbol table. If
* a symbol is found iterate over the unresolved relocation records for the
* symbol fixing up the relocations. The second stage is to search the
* archives for symbols we have not been search before and if a symbol if
* found in an archve loaded the object file. Loading an object file stops
* the search of the archives for symbols and stage one is performed
* again. The process repeats until no more symbols are resolved.
* archives for symbols we have not searched before and if a symbol is found
* in an archve load the object file. Loading an object file stops the
* search of the archives for symbols and stage one is performed again. The
* process repeats until no more symbols are resolved or there is an error.
*/
while (resolving)
{
@@ -665,18 +675,87 @@ rtems_rtl_unresolved_resolve (void)
}
bool
rtems_rtl_unresolved_remove (rtems_rtl_obj* obj,
const char* name,
const uint16_t sect,
const rtems_rtl_word* rel)
rtems_rtl_trampoline_add (rtems_rtl_obj* obj,
const uint16_t flags,
const uint16_t sect,
const rtems_rtl_word symvalue,
const rtems_rtl_word* rel)
{
rtems_rtl_unresolved* unresolved;
rtems_rtl_unresolved* unresolved;
rtems_rtl_unresolv_block* block;
rtems_rtl_unresolv_rec* rec;
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
printf ("rtl: tramp: add: %s sect:%d flags:%04x\n",
rtems_rtl_obj_oname (obj), sect, flags);
unresolved = rtems_rtl_unresolved_unprotected ();
if (unresolved == NULL)
if (!unresolved)
return false;
block = rtems_rtl_unresolved_alloc_recs (unresolved, 1);
if (block == NULL)
{
block = rtems_rtl_unresolved_block_alloc (unresolved);
if (!block)
return false;
}
rec = rtems_rtl_unresolved_rec_first_free (block);
rec->type = rtems_rtl_trampoline_reloc;
rec->rec.tramp.obj = obj;
rec->rec.tramp.flags = flags;
rec->rec.tramp.sect = sect;
rec->rec.tramp.symvalue = symvalue;
rec->rec.tramp.rel[0] = rel[0];
rec->rec.tramp.rel[1] = rel[1];
rec->rec.tramp.rel[2] = rel[2];
++block->recs;
return true;
}
void
rtems_rtl_trampoline_remove (rtems_rtl_obj* obj)
{
rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
if (unresolved)
{
/*
* Iterate over the blocks clearing any trampoline records.
*/
rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
while (!rtems_chain_is_tail (&unresolved->blocks, node))
{
rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
rtems_rtl_unresolv_rec* rec = rtems_rtl_unresolved_rec_first (block);
/*
* Search the table for a trampoline record and if found clean the
* record moving the remaining records down the block.
*/
while (!rtems_rtl_unresolved_rec_is_last (block, rec))
{
bool next_rec = true;
if (rec->type == rtems_rtl_trampoline_reloc && rec->rec.tramp.obj == obj)
{
rtems_rtl_unresolved_clean_block (block, rec, 1,
unresolved->block_recs);
next_rec = false;
}
if (next_rec)
rec = rtems_rtl_unresolved_rec_next (rec);
}
node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
block);
}
}
}
/**
* Struct to pass relocation data in the iterator.
*/
@@ -708,8 +787,10 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
rec->rec.name.length);
break;
case rtems_rtl_unresolved_reloc:
case rtems_rtl_trampoline_reloc:
if (dd->show_relocs)
printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
printf (" %3zu: 2:reloc%c: obj:%s name:%2d: sect:%d\n",
rec->type == rtems_rtl_unresolved_reloc ? 'R' : 'T',
dd->rec,
rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
rec->rec.reloc.name,

View File

@@ -477,21 +477,24 @@ rtems_rtl_find_obj (const char* name)
rtems_rtl_obj*
rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
{
rtems_chain_node* node = rtems_chain_first (&rtl->objects);
while (!rtems_chain_is_tail (&rtl->objects, node))
if (sym != NULL)
{
rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
if (rtems_rtl_obj_has_symbol (obj, sym))
return obj;
node = rtems_chain_next (node);
}
node = rtems_chain_first (&rtl->pending);
while (!rtems_chain_is_tail (&rtl->pending, node))
{
rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
if (rtems_rtl_obj_has_symbol (obj, sym))
return obj;
node = rtems_chain_next (node);
rtems_chain_node* node = rtems_chain_first (&rtl->objects);
while (!rtems_chain_is_tail (&rtl->objects, node))
{
rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
if (rtems_rtl_obj_has_symbol (obj, sym))
return obj;
node = rtems_chain_next (node);
}
node = rtems_chain_first (&rtl->pending);
while (!rtems_chain_is_tail (&rtl->pending, node))
{
rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
if (rtems_rtl_obj_has_symbol (obj, sym))
return obj;
node = rtems_chain_next (node);
}
}
return NULL;
}

View File

@@ -56,7 +56,7 @@ static void Init(rtems_task_argument arg)
exit (1);
}
for (i = 0; i < 100; ++i)
for (i = 0; i < 4; ++i)
{
printf ("--------------------------------------------------\n");
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_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 ": rtems_main_o2: %p\n", &rtems_main_o2);
rtems_main_o2 ();

View File

@@ -18,6 +18,6 @@ directives:
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.
+ Repeat 100 times.

View File

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