mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-08-19 04:42:41 +08:00
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,
|
||||
|
||||
+336
-164
File diff suppressed because it is too large
Load Diff
+40
-33
@@ -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
|
||||
|
||||
+98
-40
@@ -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)
|
||||
|
||||
@@ -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
|
||||
+109
-28
@@ -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,
|
||||
|
||||
+17
-14
@@ -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