diff options
author | Chris Johns <chrisj@rtems.org> | 2019-01-15 17:47:41 +1100 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2019-02-09 10:06:34 +1100 |
commit | d8c70ba65b13cd023b50b8aed5d91e455017cdd5 (patch) | |
tree | f78c3441ef74a7315ef4f7850bd27631bf0d2502 /cpukit/libdl/rtl-elf.c | |
parent | libdl: Fix the support for constructors and desctructors. (diff) | |
download | rtems-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/libdl/rtl-elf.c')
-rw-r--r-- | cpukit/libdl/rtl-elf.c | 57 |
1 files changed, 50 insertions, 7 deletions
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; |