From: Chris Johns <chr...@rtems.org> - 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 --- cpukit/include/rtems/rtl/rtl-obj.h | 38 +- cpukit/include/rtems/rtl/rtl-unresolved.h | 22 +- cpukit/include/rtems/rtl/rtl.h | 2 +- cpukit/libdl/rtl-allocator.c | 2 +- cpukit/libdl/rtl-elf.c | 484 +++++++++++++++------- cpukit/libdl/rtl-elf.h | 73 ++-- cpukit/libdl/rtl-mdreloc-arm.c | 122 ++++-- cpukit/libdl/rtl-mdreloc-bfin.c | 22 +- cpukit/libdl/rtl-mdreloc-h8300.c | 22 +- cpukit/libdl/rtl-mdreloc-i386.c | 18 +- cpukit/libdl/rtl-mdreloc-lm32.c | 21 +- cpukit/libdl/rtl-mdreloc-m68k.c | 174 ++++---- cpukit/libdl/rtl-mdreloc-mips.c | 24 +- cpukit/libdl/rtl-mdreloc-moxie.c | 20 +- cpukit/libdl/rtl-mdreloc-powerpc.c | 69 ++- cpukit/libdl/rtl-mdreloc-sparc.c | 26 +- cpukit/libdl/rtl-mdreloc-v850.c | 20 +- cpukit/libdl/rtl-obj.c | 138 ++++-- cpukit/libdl/rtl-shell.c | 59 ++- cpukit/libdl/rtl-trampoline.h | 94 +++++ cpukit/libdl/rtl-unresolved.c | 137 ++++-- cpukit/libdl/rtl.c | 31 +- testsuites/libtests/dl08/init.c | 2 +- testsuites/libtests/dl09/dl-o1.c | 1 + testsuites/libtests/dl09/dl09.doc | 2 +- testsuites/libtests/dl09/init.c | 2 +- 26 files changed, 1098 insertions(+), 527 deletions(-) create mode 100644 cpukit/libdl/rtl-trampoline.h diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h index 9c2b4f0300..f27ae3259d 100644 --- a/cpukit/include/rtems/rtl/rtl-obj.h +++ b/cpukit/include/rtems/rtl/rtl-obj.h @@ -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; } /** diff --git a/cpukit/include/rtems/rtl/rtl-unresolved.h b/cpukit/include/rtems/rtl/rtl-unresolved.h index efc9ce220f..df07ecb1ba 100644 --- a/cpukit/include/rtems/rtl/rtl-unresolved.h +++ b/cpukit/include/rtems/rtl/rtl-unresolved.h @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) 2012, 2018 Chris Johns <chr...@rtems.org> + * COPYRIGHT (c) 2012, 2019 Chris Johns <chr...@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; diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h index f13e33dbcb..67d7e96be3 100644 --- a/cpukit/include/rtems/rtl/rtl.h +++ b/cpukit/include/rtems/rtl/rtl.h @@ -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. diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c index 0dca6b2f9a..647c0c89a4 100644 --- a/cpukit/libdl/rtl-allocator.c +++ b/cpukit/libdl/rtl-allocator.c @@ -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, diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index 963cb4b2f4..0fa639f36f 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -1,5 +1,5 @@ /* - * COPYRIGHT (c) 2012-2018 Chris Johns <chr...@rtems.org> + * COPYRIGHT (c) 2012-2019 Chris Johns <chr...@rtems.org> * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at @@ -31,11 +31,12 @@ #include "rtl-elf.h" #include "rtl-error.h" #include <rtems/rtl/rtl-trace.h> +#include "rtl-trampoline.h" #include "rtl-unwind.h" #include <rtems/rtl/rtl-unresolved.h> /** - * The offsets in the unresolved array. + * The offsets in the reloc words. */ #define REL_R_OFFSET (0) #define REL_R_INFO (1) @@ -166,66 +167,77 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj* obj, void* data) { rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data; + rtems_rtl_word rel_words[3]; + rtems_rtl_elf_rel_status rs; /* - * The symbol has to have been resolved to parse the reloc record. Unresolved - * symbols are handled in the relocator but we need to count them here so a - * trampoline is accounted for. We have to assume the unresolved may be out of - * of range. + * Check the reloc record to see if a trampoline is needed. */ - if (!resolved) + if (is_rela) { - ++rd->unresolved; + const Elf_Rela* rela = (const Elf_Rela*) relbuf; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rela tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n", + ELF_ST_BIND (sym->st_info) == STB_GLOBAL || + ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L', + symname, (int) ELF_R_SYM (rela->r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), + (uintmax_t) rela->r_offset, (int) rela->r_addend); + rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect, + symname, sym->st_info, symvalue); + rel_words[REL_R_OFFSET] = rela->r_offset; + rel_words[REL_R_INFO] = rela->r_info; + rel_words[REL_R_ADDEND] = rela->r_addend; } else + { + const Elf_Rel* rel = (const Elf_Rel*) relbuf; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n", + ELF_ST_BIND (sym->st_info) == STB_GLOBAL || + ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L', + symname, (int) ELF_R_SYM (rel->r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), + (uintmax_t) rel->r_offset); + rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect, + symname, sym->st_info, symvalue); + rel_words[REL_R_OFFSET] = rel->r_offset; + rel_words[REL_R_INFO] = rel->r_info; + rel_words[REL_R_ADDEND] = 0; + } + + if (rs == rtems_rtl_elf_rel_failure) + return false; + + if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add) + { + uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8); + if (!rtems_rtl_trampoline_add (obj, flags, + targetsect->section, symvalue, rel_words)) + return false; + } + + /* + * Handle any dependencies if there is a valid symbol. + */ + if (symname != NULL) { /* - * Check the reloc record to see if a trampoline is needed. + * Find the symbol's object file. It cannot be NULL so ignore that result + * if returned, it means something is corrupted. We are in an iterator. */ - 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 (symname != NULL) + rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol); + if (sobj != NULL) { /* - * Find the symbol's object file. It cannot be NULL so ignore that result - * if returned, it means something is corrupted. We are in an iterator. + * A dependency is not the base kernel image or itself. Tag the object as + * having been visited so we count it only once. */ - rtems_rtl_obj* sobj = rtems_rtl_find_obj_with_symbol (symbol); - if (sobj != NULL) + if (sobj != rtems_rtl_baseimage () && obj != sobj && + (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0) { - /* - * A dependency is not the base kernel image or itself. Tag the object as - * having been visited so we count it only once. - */ - if (sobj != rtems_rtl_baseimage () && obj != sobj && - (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0) - { - sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG; - ++rd->dependents; - } + sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG; + ++rd->dependents; } } } @@ -278,7 +290,8 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj, } else { - rtems_rtl_obj* sobj; + rtems_rtl_obj* sobj; + rtems_rtl_elf_rel_status rs; if (is_rela) { @@ -287,8 +300,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj, symname, (int) ELF_R_SYM (rela->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info), (uintmax_t) rela->r_offset, (int) rela->r_addend); - if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, - symname, sym->st_info, symvalue)) + rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect, + symname, sym->st_info, symvalue); + if (rs != rtems_rtl_elf_rel_no_error) return false; } else @@ -298,8 +312,9 @@ rtems_rtl_elf_reloc_relocator (rtems_rtl_obj* obj, symname, (int) ELF_R_SYM (rel->r_info), (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info), (uintmax_t) rel->r_offset); - if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, - symname, sym->st_info, symvalue)) + rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect, + symname, sym->st_info, symvalue); + if (rs != rtems_rtl_elf_rel_no_error) return false; } @@ -419,7 +434,10 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj* obj, /* * Only need the name of the symbol if global or a common symbol. */ - if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE || + if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT || + ELF_ST_TYPE (sym.st_info) == STT_COMMON || + ELF_ST_TYPE (sym.st_info) == STT_FUNC || + ELF_ST_TYPE (sym.st_info) == STT_NOTYPE || ELF_ST_TYPE (sym.st_info) == STT_TLS || sym.st_shndx == SHN_COMMON) { @@ -491,10 +509,11 @@ bool rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, rtems_rtl_obj_sym* sym) { - rtems_rtl_obj_sect* sect; - bool is_rela; - Elf_Word symvalue; - rtems_rtl_obj* sobj; + rtems_rtl_obj_sect* sect; + bool is_rela; + Elf_Word symvalue; + rtems_rtl_obj* sobj; + rtems_rtl_elf_rel_status rs; is_rela = reloc->flags & 1; @@ -516,8 +535,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, printf ("rtl: rela: sym:%d type:%d off:%08jx addend:%d\n", (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info), (uintmax_t) rela.r_offset, (int) rela.r_addend); - if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect, - sym->name, sym->data, symvalue)) + rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect, + sym->name, sym->data, symvalue); + if (rs != rtems_rtl_elf_rel_no_error) return false; } else @@ -529,8 +549,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc, printf ("rtl: rel: sym:%d type:%d off:%08jx\n", (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info), (uintmax_t) rel.r_offset); - if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect, - sym->name, sym->data, symvalue)) + rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect, + sym->name, sym->data, symvalue); + if (rs != rtems_rtl_elf_rel_no_error) return false; } @@ -621,16 +642,117 @@ rtems_rtl_elf_common (rtems_rtl_obj* obj, return true; } +/** + * Struct to handle trampoline reloc recs in the unresolved table. + */ +typedef struct rtems_rtl_tramp_data +{ + bool failure; + rtems_rtl_obj* obj; + size_t count; + size_t total; +} rtems_rtl_tramp_data; + +static bool +rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec, + void* data) +{ + rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data; + if (rec->type == rtems_rtl_trampoline_reloc) + { + const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp; + + ++td->total; + + if (tramp->obj == td->obj) + { + const rtems_rtl_obj_sect* targetsect; + Elf_Byte st_info; + Elf_Word symvalue; + rtems_rtl_elf_rel_status rs; + bool* failure = (bool*) data; + const bool is_rela = (tramp->flags & 1) == 1; + const bool unresolved = (tramp->flags & (1 << 1)) != 0; + + ++td->count; + + targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect); + st_info = tramp->flags >> 8; + symvalue = tramp->symvalue; + + if (is_rela) + { + Elf_Rela rela = { + .r_offset = tramp->rel[REL_R_OFFSET], + .r_info = tramp->rel[REL_R_INFO], + .r_addend = tramp->rel[REL_R_ADDEND] + }; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n", + ELF_ST_BIND (st_info) == STB_GLOBAL || + ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L', + (int) ELF_R_SYM (rela.r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rela.r_info), + (uintmax_t) rela.r_offset, (int) rela.r_addend); + rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect, + NULL, st_info, symvalue); + } + else + { + Elf_Rel rel = { + .r_offset = tramp->rel[REL_R_OFFSET], + .r_info = tramp->rel[REL_R_INFO], + }; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n", + ELF_ST_BIND (st_info) == STB_GLOBAL || + ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L', + (int) ELF_R_SYM (rel.r_info), + (uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info), + (uintmax_t) rel.r_offset); + rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect, + NULL, st_info, symvalue); + } + + if (unresolved || rs == rtems_rtl_elf_rel_tramp_add) + tramp->obj->tramps_size += tramp->obj->tramp_size; + if (rs == rtems_rtl_elf_rel_failure) + { + *failure = true; + return true; + } + } + } + + return false; +} + static bool rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved) { + rtems_rtl_tramp_data td = { 0 }; + td.obj = obj; + /* + * See which relocs are out of range and need a trampoline. + */ + rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td); + if (td.failure) + return false; + rtems_rtl_trampoline_remove (obj); + obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n", + obj->tramp_relocs, td.count, td.total); /* * Add on enough space to handle the unresolved externals that need to be * resolved at some point in time. They could all require fixups and * trampolines. */ - obj->tramp_size += - rtems_rtl_elf_relocate_tramp_max_size () * unresolved; + obj->tramps_size += obj->tramp_size * unresolved; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: tramp:elf: slots: %zu (%zu)\n", + obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size, + obj->tramps_size); return rtems_rtl_obj_alloc_trampoline (obj); } @@ -653,10 +775,10 @@ rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc) } static bool -rtems_rtl_elf_symbols (rtems_rtl_obj* obj, - int fd, - rtems_rtl_obj_sect* sect, - void* data) +rtems_rtl_elf_symbols_load (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect* sect, + void* data) { rtems_rtl_obj_cache* symbols; rtems_rtl_obj_cache* strings; @@ -720,19 +842,20 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj, * we need to make sure there is a valid seciton. */ if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) - printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \ - "type:%-2d sect:%d size:%d\n", + printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d " \ + "type:%-2d sect:%-5d size:%-5d value:%d\n", sym, (int) symbol.st_name, name, (int) ELF_ST_BIND (symbol.st_info), (int) ELF_ST_TYPE (symbol.st_info), symbol.st_shndx, - (int) symbol.st_size); + (int) symbol.st_size, + (int) symbol.st_value); - /* - * If a duplicate forget it. - */ - if (rtems_rtl_symbol_global_find (name)) - continue; + /* + * If a duplicate forget it. + */ + if (rtems_rtl_symbol_global_find (name)) + continue; if ((symbol.st_shndx != 0) && ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) || @@ -775,7 +898,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj, else { if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) - printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n", + printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n", sym, (int) symbol.st_name, name); ++globals; global_string_space += strlen (name) + 1; @@ -784,7 +907,7 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj, else if (ELF_ST_BIND (symbol.st_info) == STB_LOCAL) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) - printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n", + printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n", sym, (int) symbol.st_name, name); ++locals; local_string_space += strlen (name) + 1; @@ -849,14 +972,14 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj, if (!rtems_rtl_obj_cache_read_byval (symbols, fd, off, &symbol, sizeof (symbol))) { - if (locals) + if (obj->local_syms) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table); obj->local_table = NULL; obj->local_size = 0; obj->local_syms = 0; } - if (globals) + if (obj->global_syms) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table); obj->global_table = NULL; @@ -875,78 +998,113 @@ rtems_rtl_elf_symbols (rtems_rtl_obj* obj, (ELF_ST_BIND (symbol.st_info) == STB_WEAK) || (ELF_ST_BIND (symbol.st_info) == STB_LOCAL))) { - rtems_rtl_obj_sect* symsect; - rtems_rtl_obj_sym* osym; - char* string; - Elf_Word value; + rtems_rtl_obj_sym* osym; + char* string; + Elf_Word value; + const char* name; - symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx); - if (symsect) + off = obj->ooffset + strtab->offset + symbol.st_name; + len = RTEMS_RTL_ELF_STRING_MAX; + + if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len)) + return false; + + /* + * If a duplicate forget it. + */ + if (rtems_rtl_symbol_global_find (name)) + continue; + + if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) || + (ELF_ST_BIND (symbol.st_info) == STB_WEAK)) + { + osym = gsym; + string = gstring; + gstring += strlen (name) + 1; + ++gsym; + } + else { - const char* name; + osym = lsym; + string = lstring; + lstring += strlen (name) + 1; + ++lsym; + } - off = obj->ooffset + strtab->offset + symbol.st_name; - len = RTEMS_RTL_ELF_STRING_MAX; + /* + * Allocate any common symbols in the common section. + */ + if (symbol.st_shndx == SHN_COMMON) + { + size_t value_off = rtems_rtl_obj_align (common_offset, + symbol.st_value); + common_offset = value_off + symbol.st_size; + value = value_off; + } + else + { + value = symbol.st_value; + } - if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len)) - return false; + rtems_chain_set_off_chain (&osym->node); + memcpy (string, name, strlen (name) + 1); + osym->name = string; + osym->value = (uint8_t*) value; + osym->data = symbol.st_shndx; - /* - * If a duplicate forget it. - */ - if (rtems_rtl_symbol_global_find (name)) - continue; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) + printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \ + "type:%-2d val:%-8p sect:%-3d size:%d\n", + sym, (int) symbol.st_name, osym->name, + (int) ELF_ST_BIND (symbol.st_info), + (int) ELF_ST_TYPE (symbol.st_info), + osym->value, symbol.st_shndx, + (int) symbol.st_size); + } + } - if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) || - (ELF_ST_BIND (symbol.st_info) == STB_WEAK)) - { - osym = gsym; - string = gstring; - gstring += strlen (name) + 1; - ++gsym; - } - else - { - osym = lsym; - string = lstring; - lstring += strlen (name) + 1; - ++lsym; - } + return true; +} - /* - * Allocate any common symbols in the common section. - */ - if (symbol.st_shndx == SHN_COMMON) - { - size_t value_off = rtems_rtl_obj_align (common_offset, - symbol.st_value); - common_offset = value_off + symbol.st_size; - value = value_off; - } - else - { - value = symbol.st_value; - } +static bool +rtems_rtl_elf_symbols_locate (rtems_rtl_obj* obj, + int fd, + rtems_rtl_obj_sect* sect, + void* data) +{ + int sym; - rtems_chain_set_off_chain (&osym->node); - memcpy (string, name, strlen (name) + 1); - osym->name = string; - osym->value = value + (uint8_t*) symsect->base; - osym->data = symbol.st_info; + for (sym = 0; sym < obj->local_syms; ++sym) + { + rtems_rtl_obj_sym* osym = &obj->local_table[sym]; + rtems_rtl_obj_sect* symsect; + symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data); + if (symsect) + { + osym->value += (intptr_t) symsect->base; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) + printf ("rtl: sym:locate:local :%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n", + sym, osym->name, osym->value, osym->data, + symsect->name, symsect->base); + } + } + for (sym = 0; sym < obj->global_syms; ++sym) + { + rtems_rtl_obj_sym* osym = &obj->global_table[sym]; + rtems_rtl_obj_sect* symsect; + symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data); + if (symsect) + { + osym->value += (intptr_t) symsect->base; if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL)) - printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \ - "type:%-2d val:%8p sect:%d size:%d\n", - sym, (int) symbol.st_name, osym->name, - (int) ELF_ST_BIND (symbol.st_info), - (int) ELF_ST_TYPE (symbol.st_info), - osym->value, symbol.st_shndx, - (int) symbol.st_size); + printf ("rtl: sym:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n", + sym, osym->name, osym->value, osym->data, + symsect->name, symsect->base); } - } } - if (globals) + if (obj->global_size) rtems_rtl_symbol_obj_add (obj); return true; @@ -1434,6 +1592,11 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) return false; } + /* + * Set the format's architecture's maximum tramp size. + */ + obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size (); + /* * Parse the section information first so we have the memory map of the object * file and the memory allocated. Any further allocations we make to complete @@ -1443,18 +1606,31 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) return false; /* - * See if there are any common variables and if there are add a common - * section. + * Set the entry point if there is one. + */ + obj->entry = (void*)(uintptr_t) ehdr.e_entry; + + /* + * Load the symbol table. + * + * 1. See if there are any common variables and if there are add a + * common section. + * 2. Add up the common. + * 3. */ if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common)) return false; if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment)) return false; + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &ehdr)) + return false; /* - * Set the entry point if there is one. + * Parse the relocation records. It lets us know how many dependents + * and fixup trampolines there are. */ - obj->entry = (void*)(uintptr_t) ehdr.e_entry; + if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs)) + return false; /* * Lock the allocator so the section memory and the trampoline memory are as @@ -1468,17 +1644,7 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) if (!rtems_rtl_obj_alloc_sections (obj, fd, rtems_rtl_elf_arch_alloc, &ehdr)) return false; - /* - * Load the sections and symbols and then relocation to the base address. - */ - if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr)) - return false; - - /* - * Parse the relocation records. It lets us know how many dependents - * and fixup trampolines there are. - */ - if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs)) + if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr)) return false; if (!rtems_rtl_elf_dependents (obj, &relocs)) @@ -1492,9 +1658,15 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd) */ rtems_rtl_alloc_unlock (); - if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr)) + /* + * Load the sections and symbols and then relocation to the base address. + */ + if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr)) return false; + /* + * Fix up the relocations. + */ if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr)) return false; diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h index 73d1e01bb1..660b0c47b4 100644 --- a/cpukit/libdl/rtl-elf.h +++ b/cpukit/libdl/rtl-elf.h @@ -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. diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index b0c55c257a..4d5a2456a7 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -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 (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 (parsing) + { + addend = 0; + } + else + { + insn = *where; + + 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 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, diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c index af130276a4..27f865e5a5 100644 --- a/cpukit/libdl/rtl-mdreloc-bfin.c +++ b/cpukit/libdl/rtl-mdreloc-bfin.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c index 4a12f34f36..f1a52e4f9d 100644 --- a/cpukit/libdl/rtl-mdreloc-h8300.c +++ b/cpukit/libdl/rtl-mdreloc-h8300.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c index 576914cf04..40b09d4be2 100644 --- a/cpukit/libdl/rtl-mdreloc-i386.c +++ b/cpukit/libdl/rtl-mdreloc-i386.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c index 9f4606ebad..4d47592e12 100644 --- a/cpukit/libdl/rtl-mdreloc-lm32.c +++ b/cpukit/libdl/rtl-mdreloc-lm32.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c index 21a60ee62a..873574ef7c 100644 --- a/cpukit/libdl/rtl-mdreloc-m68k.c +++ b/cpukit/libdl/rtl-mdreloc-m68k.c @@ -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(PC8): - tmp = symvalue + rela->r_addend - (Elf_Addr)where; - if (overflow_8_check(tmp)) - return false; - - *(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; - - case R_TYPE(PC16): - tmp = symvalue + rela->r_addend - (Elf_Addr)where; - if (overflow_16_check(tmp)) - return false; - - *(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 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; - - 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; - - 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; - - 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; + case R_TYPE(NONE): + break; + + 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; + + 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 rtems_rtl_elf_rel_failure; + + *(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 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; + + 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; + + 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; + + 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 diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c index f01a6552a5..c37804880f 100644 --- a/cpukit/libdl/rtl-mdreloc-mips.c +++ b/cpukit/libdl/rtl-mdreloc-mips.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c index 68fa2d2a16..8c7169e532 100644 --- a/cpukit/libdl/rtl-mdreloc-moxie.c +++ b/cpukit/libdl/rtl-mdreloc-moxie.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c index 0a9703984d..48ecee58e5 100644 --- a/cpukit/libdl/rtl-mdreloc-powerpc.c +++ b/cpukit/libdl/rtl-mdreloc-powerpc.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c index f76da575e4..548c24132b 100644 --- a/cpukit/libdl/rtl-mdreloc-sparc.c +++ b/cpukit/libdl/rtl-mdreloc-sparc.c @@ -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 diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c index 93e531b40e..859225ca6f 100644 --- a/cpukit/libdl/rtl-mdreloc-v850.c +++ b/cpukit/libdl/rtl-mdreloc-v850.c @@ -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 diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index 378678435d..9acb6f3943 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -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; } diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c index 56418303ff..4c80ae5db1 100644 --- a/cpukit/libdl/rtl-shell.c +++ b/cpukit/libdl/rtl-shell.c @@ -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) diff --git a/cpukit/libdl/rtl-trampoline.h b/cpukit/libdl/rtl-trampoline.h new file mode 100644 index 0000000000..e04c20863b --- /dev/null +++ b/cpukit/libdl/rtl-trampoline.h @@ -0,0 +1,94 @@ +/* + * COPYRIGHT (c) 2019 Chris Johns <chr...@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 diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c index dc21e9bcc1..fbfe909d2e 100644 --- a/cpukit/libdl/rtl-unresolved.c +++ b/cpukit/libdl/rtl-unresolved.c @@ -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, diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c index e3dba5a206..d4103bace6 100644 --- a/cpukit/libdl/rtl.c +++ b/cpukit/libdl/rtl.c @@ -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; } diff --git a/testsuites/libtests/dl08/init.c b/testsuites/libtests/dl08/init.c index 87f7f9b142..d1f01a56bd 100644 --- a/testsuites/libtests/dl08/init.c +++ b/testsuites/libtests/dl08/init.c @@ -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); diff --git a/testsuites/libtests/dl09/dl-o1.c b/testsuites/libtests/dl09/dl-o1.c index 438c05eee9..9404a45732 100644 --- a/testsuites/libtests/dl09/dl-o1.c +++ b/testsuites/libtests/dl09/dl-o1.c @@ -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 (); diff --git a/testsuites/libtests/dl09/dl09.doc b/testsuites/libtests/dl09/dl09.doc index 4c5d97ef2a..f9df9a276d 100644 --- a/testsuites/libtests/dl09/dl09.doc +++ b/testsuites/libtests/dl09/dl09.doc @@ -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. diff --git a/testsuites/libtests/dl09/init.c b/testsuites/libtests/dl09/init.c index dbcc7ba84c..5343a1dcdf 100644 --- a/testsuites/libtests/dl09/init.c +++ b/testsuites/libtests/dl09/init.c @@ -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); -- 2.19.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel