summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-01-15 17:47:41 +1100
committerChris Johns <chrisj@rtems.org>2019-02-09 10:06:34 +1100
commitd8c70ba65b13cd023b50b8aed5d91e455017cdd5 (patch)
treef78c3441ef74a7315ef4f7850bd27631bf0d2502 /cpukit
parentlibdl: Fix the support for constructors and desctructors. (diff)
downloadrtems-d8c70ba65b13cd023b50b8aed5d91e455017cdd5.tar.bz2
libdl: Add support for trampolines
- Trampolines or fixups for veneers provide long jump support for instruciton sets that implement short relative address branches. The linker provides trampolines when creating a static image. This patch adds trampoline support to libdl and the ARM architecture. - The dl09 test requires enough memory so modules are outside the relative branch instruction ranges for the architecture. Updates #3685
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/include/rtems/rtl/rtl-obj.h38
-rw-r--r--cpukit/libdl/rtl-elf.c57
-rw-r--r--cpukit/libdl/rtl-elf.h64
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c301
-rw-r--r--cpukit/libdl/rtl-mdreloc-bfin.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-h8300.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-i386.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-lm32.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-m68k.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-mips.c70
-rw-r--r--cpukit/libdl/rtl-mdreloc-moxie.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-powerpc.c56
-rw-r--r--cpukit/libdl/rtl-mdreloc-sparc.c54
-rw-r--r--cpukit/libdl/rtl-mdreloc-v850.c54
-rw-r--r--cpukit/libdl/rtl-obj.c33
15 files changed, 925 insertions, 126 deletions
diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index b7522a7d39..4ce356015c 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -1,5 +1,5 @@
/*
- * COPYRIGHT (c) 2012 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
@@ -220,6 +220,12 @@ struct rtems_rtl_obj
uint32_t* sec_num; /**< The sec nums of each obj. */
uint32_t obj_num; /**< The count of elf files in an rtl
* obj. */
+ void* trampoline; /**< Trampoline memory. Used for fixups or
+ * veneers */
+ size_t tramp_size; /**< Size of the tramopline memory. */
+ void* tramp_brk; /**< Trampoline memory allocator. MD
+ * relocators can take memory from the
+ * break upto the size. */
struct link_map* linkmap; /**< For GDB. */
void* loader; /**< The file details specific to a
* loader. */
@@ -353,6 +359,20 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj* obj,
}
/**
+ * Is there space in the trampoline memory for a trapoline.
+ *
+ * @param obj The object file's descriptor to check for available space.
+ * @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)
+{
+ return (obj->trampoline != NULL &&
+ ((obj->tramp_brk - obj->trampoline) + size) <= obj->tramp_size);
+}
+
+/**
* Allocate an object structure on the heap.
*
* @retval NULL No memory for the object.
@@ -477,6 +497,22 @@ rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj
uint32_t mask);
/**
+ * Allocate a table for trampoline fixup calls.
+ *
+ * @param obj The object file's descriptor.
+ * @retval true The table was allocated.
+ * @retval false The alloction failed.
+ */
+bool rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj);
+
+/**
+ * Erase the object file descriptor's trampoline table..
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj);
+
+/**
* Allocate a table for dependent objects.
*
* @param obj The object file's descriptor.
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 63242acaae..96af16cb52 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -87,10 +87,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
*/
*symbol = rtems_rtl_symbol_obj_find (obj, symname);
if (!*symbol)
- {
- rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
return false;
- }
*value = (Elf_Addr) (*symbol)->value;
return true;
@@ -100,10 +97,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
if (!sect)
- {
- rtems_rtl_set_error (EINVAL, "reloc symbol's section not found");
return false;
- }
*value = sym->st_value + (Elf_Addr) sect->base;
return true;
@@ -145,6 +139,35 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
void* data)
{
rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
+
+ /*
+ * 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;
+ }
+
/*
* If the symbol has been resolved and there is a symbol name it is a global
* symbol and from another object file so add it as a dependency.
@@ -153,7 +176,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj,
{
++rd->unresolved;
}
- else if (resolved && symname != NULL)
+ else if (symname != NULL)
{
/*
* Find the symbol's object file. It cannot be NULL so ignore that result
@@ -557,6 +580,19 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj,
}
static bool
+rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
+{
+ /*
+ * 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;
+ return rtems_rtl_obj_alloc_trampoline (obj);
+}
+
+static bool
rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
{
/*
@@ -1297,12 +1333,19 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
return false;
+ /*
+ * Parse the relocation records. It lets us know how many dependents
+ * and fixup trampolines there are.
+ */
if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
return false;
if (!rtems_rtl_elf_dependents (obj, &relocs))
return false;
+ if (!rtems_rtl_elf_alloc_trampoline (obj, relocs.unresolved))
+ return false;
+
if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
return false;
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index 1f5f82eb89..d781bfb3a4 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -52,6 +52,16 @@ extern "C" {
**/
/**
+ * Relocation trampoline relocation data.
+ */
+typedef struct rtems_rtl_mdreloc_trmap
+{
+ bool parsing; /**< The reloc records are being parsed. */
+ void* tampolines; /**< The trampoline memory. */
+ size_t size; /**< The trampoline size. */
+} rtems_rtl_mdreloc_tramp;
+
+/**
* Maximum string length. This a read buffering limit rather than a
* specific ELF length. I hope this is ok as I am concerned about
* some C++ symbol lengths.
@@ -81,6 +91,56 @@ uint32_t rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
/**
+ * Architecture specific relocation maximum trampoline size. A trampoline entry
+ * of this size is allocated for each unresolved external.
+ *
+ * @return size_t The maximum size of a trampoline for this architecture.
+ */
+size_t rtems_rtl_elf_relocate_tramp_max_size (void);
+
+/**
+ * Architecture specific relocation trampoline handler compiled in for a
+ * specific architecture by the build system. The handler determines if the
+ * relocation record requires a trampoline.
+ *
+ * @param obj The object file being relocated.
+ * @param rel 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.
+ */
+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);
+
+/**
+ * Architecture specific relocation handler compiled in for a specific
+ * architecture by the build system. The handler applies the relocation
+ * to the target.
+ *
+ * @param obj The object file being relocated.
+ * @param rela The ELF addend 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.
+ */
+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);
+
+/**
* Architecture specific relocation handler compiled in for a specific
* architecture by the build system. The handler applies the relocation
* to the target.
@@ -94,7 +154,7 @@ bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
* @retval bool The relocation has been applied.
* @retval bool The relocation could not be applied.
*/
-bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -115,7 +175,7 @@ bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
* @retval bool The relocation has been applied.
* @retval bool The relocation could not be applied.
*/
-bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+bool rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index ef00701d32..a00f0f8825 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -33,18 +33,17 @@
static inline Elf_Addr
load_ptr(void *where)
{
- Elf_Addr res;
+ Elf_Addr res;
- memcpy(&res, where, sizeof(res));
+ memcpy(&res, where, sizeof(res));
- return (res);
+ return (res);
}
static inline void
store_ptr(void *where, Elf_Addr val)
{
-
- memcpy(where, &val, sizeof(val));
+ memcpy(where, &val, sizeof(val));
}
/*
@@ -67,6 +66,33 @@ sign_extend31(Elf_Addr val)
return 0x7fffffff & val;
}
+static void*
+set_veneer(void* tramopline, Elf_Addr target)
+{
+ /*
+ * http://shell-storm.org/online/Online-Assembler-and-Disassembler/
+ *
+ * ldr.w pc, [pc]
+ */
+ uint32_t* tramp = (uint32_t*) tramopline;
+ *tramp++ = 0xf000f8df;
+ *tramp++ = (uint32_t) target;
+ return tramp;
+}
+
+static size_t
+get_veneer_size(int type)
+{
+ (void) type;
+ return 8;
+}
+
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ return 8;
+}
+
uint32_t
rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
const Elf_Shdr* shdr)
@@ -84,24 +110,49 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
}
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
}
-bool
-rtems_rtl_elf_relocate_rel (const 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)
+static bool
+rtems_rtl_elf_relor_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,
+ const bool parsing)
{
Elf_Addr *where;
Elf_Addr tmp;
@@ -142,21 +193,40 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
tmp = (Elf_Sword)tmp >> 2;
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
- printf("CALL/JUMP24 Overflow\n");
- return false;
- }
+ Elf_Word tramp_addr;
+ size_t tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
- *where = (*where & 0xff000000) | (tmp & 0xffffff);
+ if (parsing) {
+ obj->tramp_size += tramp_size;
+ return true;
+ }
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+ rtems_rtl_set_error (EINVAL,
+ "%s: CALL/JUMP24: overflow: no tramp memory",
+ sect->name);
+ return false;
+ }
+ tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+ obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
+
+ tmp = tramp_addr + (addend << 2) - (Elf_Addr)where;
+ tmp = (Elf_Sword)tmp >> 2;
+ }
+
+ if (!parsing) {
+ *where = (*where & 0xff000000) | (tmp & 0xffffff);
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(V4BX):
/* Miscellaneous, ignore */
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ if (!parsing && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
printf ("rtl: V4BX %p @ %p in %s\n",
(void *)*where, where, rtems_rtl_obj_oname (obj));
}
@@ -182,72 +252,78 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
}
}
- *where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
+ if (!parsing) {
+ *where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
break;
-
case R_TYPE(REL32): /* word32 (S + A) | T - P */
case R_TYPE(ABS32): /* word32 (S + A) | T */
case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */
case R_TYPE(PREL31): /* word32 (S + A) | T - P */
case R_TYPE(TARGET1): /* Equivalent to ABS32 */
case R_TYPE(TARGET2): /* Equivalent to REL32 */
- if (__predict_true(RELOC_ALIGNED_P(where))) {
- tmp = *where + symvalue;
- if (isThumb(symvalue))
- tmp |= 1;
- if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
- ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
- tmp -= (Elf_Addr)where;
- else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
- tmp = sign_extend31(tmp - (Elf_Addr)where);
- *where = tmp;
- } else {
- tmp = load_ptr(where) + symvalue;
- if (isThumb(symvalue))
- tmp |= 1;
- if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
- ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
- tmp -= (Elf_Addr)where;
- else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
- tmp = sign_extend31(tmp - (Elf_Addr)where);
- store_ptr(where, tmp);
- }
+ if (!parsing) {
+ if (__predict_true(RELOC_ALIGNED_P(where))) {
+ tmp = *where + symvalue;
+ if (isThumb(symvalue))
+ tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
+ ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
+ tmp -= (Elf_Addr)where;
+ else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
+ tmp = sign_extend31(tmp - (Elf_Addr)where);
+ if (!parsing) {
+ *where = tmp;
+ }
+ } else {
+ tmp = load_ptr(where) + symvalue;
+ if (isThumb(symvalue))
+ tmp |= 1;
+ if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
+ ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
+ tmp -= (Elf_Addr)where;
+ else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
+ tmp = sign_extend31(tmp - (Elf_Addr)where);
+ store_ptr(where, tmp);
+ }
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
- printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s\n",
- (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+ printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s\n",
+ (void *)tmp, where, rtems_rtl_obj_oname (obj));
+ }
break;
case R_TYPE(THM_MOVT_ABS):
case R_TYPE(THM_MOVW_ABS_NC):
- upper_insn = *(uint16_t *)where;
- lower_insn = *((uint16_t *)where + 1);
-
- addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
- ((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
- addend = (addend ^ 0x8000) - 0x8000;
-
- tmp = addend + symvalue;
- if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
- tmp >>= 16;
-
- *(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
- ((tmp & 0xf000) >> 12) |
- ((tmp & 0x0800) >> 1));
- *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
- ((tmp & 0x0700) << 4) |
- (tmp & 0x00ff));
-
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
- printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ if (!parsing) {
+ upper_insn = *(uint16_t *)where;
+ lower_insn = *((uint16_t *)where + 1);
+
+ addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
+ ((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
+ addend = (addend ^ 0x8000) - 0x8000;
+
+ tmp = addend + symvalue;
+ if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
+ tmp >>= 16;
+
+ *(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
+ ((tmp & 0xf000) >> 12) |
+ ((tmp & 0x0800) >> 1));
+ *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
+ ((tmp & 0x0700) << 4) |
+ (tmp & 0x00ff));
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+ printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
}
-
break;
case R_TYPE(THM_JUMP24):
@@ -278,24 +354,44 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
tmp = tmp - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
- printf("THM_CALL/JUMP24 overflow\n");
- return false;
- }
+ 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_obj_has_ramp_space (obj, tramp_size)) {
+ rtems_rtl_set_error (EINVAL,
+ "%s: THM_CALL/JUMP24: overflow: no tramp memory",
+ sect->name);
+ return false;
+ }
- sign = (tmp >> 24) & 1;
- *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
- ((tmp >> 12) & 0x3ff));
+ tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+ obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
- *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
- ((sign ^ (~(tmp >> 23) & 1)) << 13) |
- ((sign ^ (~(tmp >> 22) & 1)) << 11) |
- ((tmp >> 1) & 0x7ff));
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
- printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
- (void *)*where, where, rtems_rtl_obj_oname (obj));
+ tmp = tramp_addr + addend;
+ tmp = tmp - (Elf_Addr)where;
}
+ if (!parsing) {
+ sign = (tmp >> 24) & 1;
+ *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
+ ((tmp >> 12) & 0x3ff));
+
+ *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
+ ((sign ^ (~(tmp >> 23) & 1)) << 13) |
+ ((sign ^ (~(tmp >> 22) & 1)) << 11) |
+ ((tmp >> 1) & 0x7ff));
+
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
+ printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
+ (void *)*where, where, rtems_rtl_obj_oname (obj));
+ }
+ }
break;
case R_TYPE(THM_JUMP19):
@@ -327,6 +423,7 @@ rtems_rtl_elf_relocate_rel (const 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;
}
@@ -359,6 +456,40 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
}
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)
+{
+ return rtems_rtl_elf_relor_rel (obj,
+ rel,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ true);
+}
+
+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)
+{
+ return rtems_rtl_elf_relor_rel (obj,
+ rel,
+ sect,
+ symname,
+ syminfo,
+ symvalue,
+ false);
+}
+
+bool
rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
const char* name,
uint32_t flags)
diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c
index e1190046a3..b4c20fac24 100644
--- a/cpukit/libdl/rtl-mdreloc-bfin.c
+++ b/cpukit/libdl/rtl-mdreloc-bfin.c
@@ -32,8 +32,34 @@ load_ptr(void *where)
return (res);
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -112,13 +138,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c
index 54af83973f..e0cb826dc8 100644
--- a/cpukit/libdl/rtl-mdreloc-h8300.c
+++ b/cpukit/libdl/rtl-mdreloc-h8300.c
@@ -25,8 +25,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -98,13 +124,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
index f0aa61b8ee..773ef8e916 100644
--- a/cpukit/libdl/rtl-mdreloc-i386.c
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -31,20 +31,70 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rel,
const rtems_rtl_obj_sect* sect,
const char* symname,
const Elf_Byte syminfo,
const Elf_Word symvalue)
{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
const char* symname,
diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c
index ad59ec2e09..cf64ea8fb3 100644
--- a/cpukit/libdl/rtl-mdreloc-lm32.c
+++ b/cpukit/libdl/rtl-mdreloc-lm32.c
@@ -25,8 +25,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -117,13 +143,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c
index f42899b118..1981e93d56 100644
--- a/cpukit/libdl/rtl-mdreloc-m68k.c
+++ b/cpukit/libdl/rtl-mdreloc-m68k.c
@@ -45,8 +45,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symnane,
@@ -145,13 +171,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c
index 7ad18b382f..4860fdfe72 100644
--- a/cpukit/libdl/rtl-mdreloc-mips.c
+++ b/cpukit/libdl/rtl-mdreloc-mips.c
@@ -25,18 +25,68 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rela type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rela type record not supported");
return false;
}
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
/*
* 1. _gp_disp symbol are not considered in this file.
* 2. There is a local/external column;
@@ -46,7 +96,7 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
* just consider symtype here.
*/
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj* obj,
const Elf_Rel* rel,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -183,16 +233,16 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
break;
- default:
- printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
- "contents = %p\n",
+ default:
+ printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ "contents = %p\n",
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
(void *)rel->r_offset, (void *)*where);
- rtems_rtl_set_error (EINVAL,
- "%s: Unsupported relocation type %ld "
- "in non-PLT relocations",
- sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
- return false;
+ rtems_rtl_set_error (EINVAL,
+ "%s: Unsupported relocation type %ld "
+ "in non-PLT relocations",
+ sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+ return false;
}
return true;
diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c
index 68cbeeceb2..cc0558eaa5 100644
--- a/cpukit/libdl/rtl-mdreloc-moxie.c
+++ b/cpukit/libdl/rtl-mdreloc-moxie.c
@@ -26,8 +26,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -85,13 +111,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
index e59c415828..b205ed5215 100644
--- a/cpukit/libdl/rtl-mdreloc-powerpc.c
+++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
@@ -36,8 +36,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -198,14 +224,38 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
- printf ("rtl: rel type record not supported; please report\n");
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
index c0860a3d3f..bc05392659 100644
--- a/cpukit/libdl/rtl-mdreloc-sparc.c
+++ b/cpukit/libdl/rtl-mdreloc-sparc.c
@@ -144,8 +144,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return RELOC_RESOLVE_SYMBOL (type) ? true : false;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -261,13 +287,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
printf ("rtl: rel type record not supported; please report\n");
return false;
}
diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c
index cc2a1fa10e..2aca5e0270 100644
--- a/cpukit/libdl/rtl-mdreloc-v850.c
+++ b/cpukit/libdl/rtl-mdreloc-v850.c
@@ -26,8 +26,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
return true;
}
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+ /*
+ * Disable by returning 0.
+ */
+ return 0;
+}
+
bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rela;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj* obj,
const Elf_Rela* rela,
const rtems_rtl_obj_sect* sect,
const char* symname,
@@ -94,13 +120,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj* obj,
}
bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
+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)
+{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
+ rtems_rtl_set_error (EINVAL, "rel type record not supported");
+ return false;
+}
+
+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)
{
+ (void) obj;
+ (void) rel;
+ (void) sect;
+ (void) symname;
+ (void) syminfo;
+ (void) symvalue;
rtems_rtl_set_error (EINVAL, "rel type record not supported");
return false;
}
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 858713dee1..6f1f2e4916 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -118,6 +118,7 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj)
rtems_rtl_obj_erase_sections (obj);
rtems_rtl_obj_erase_dependents (obj);
rtems_rtl_symbol_obj_erase (obj);
+ rtems_rtl_obj_erase_trampoline (obj);
rtems_rtl_obj_free_names (obj);
if (obj->sec_num != NULL)
free (obj->sec_num);
@@ -557,6 +558,26 @@ 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)
+ return true;
+ obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+ obj->tramp_size,
+ true);
+ if (obj->trampoline == NULL)
+ rtems_rtl_set_error (ENOMEM, "no memory for the trampoline");
+ obj->tramp_brk = obj->trampoline;
+ return obj->trampoline != NULL;
+}
+
+void
+rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj)
+{
+ rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline);
+}
+
+bool
rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
{
rtems_rtl_obj_depends* depends;
@@ -837,9 +858,17 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
rtems_rtl_obj_sect_sync_handler,
&sync_ctx);
- if (sync_ctx.end_va != sync_ctx.start_va) {
+ if (sync_ctx.end_va != sync_ctx.start_va)
+ {
+ size_t size = sync_ctx.end_va - sync_ctx.start_va;
rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
- sync_ctx.end_va - sync_ctx.start_va);
+ size);
+ }
+
+ if (obj->trampoline != NULL)
+ {
+ rtems_cache_instruction_sync_after_code_change(obj->trampoline,
+ obj->tramp_size);
}
}