forked from Imagelibrary/rtems
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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
94
cpukit/libdl/rtl-trampoline.h
Normal file
94
cpukit/libdl/rtl-trampoline.h
Normal 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
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 ();
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user