From d2e31f70c12f6363cef79ffad781df6ec0acdfb5 Mon Sep 17 00:00:00 2001 From: Chris Johns Date: Tue, 28 Mar 2017 17:23:05 +1100 Subject: libdl: Back port C++ exception throw and catch from 4.12. Closes #2956. --- cpukit/Makefile.am | 2 +- cpukit/libdl/Makefile.am | 1 + cpukit/libdl/dlfcn.c | 2 +- .../libdl/include/arch/arm/machine/elf_machdep.h | 3 +- cpukit/libdl/include/sys/exec_elf.h | 10 +- cpukit/libdl/rap.c | 1 + cpukit/libdl/rtl-allocator.c | 26 +- cpukit/libdl/rtl-allocator.h | 7 +- cpukit/libdl/rtl-debugger.c | 14 +- cpukit/libdl/rtl-elf.c | 106 +++++-- cpukit/libdl/rtl-elf.h | 26 +- cpukit/libdl/rtl-error.c | 17 +- cpukit/libdl/rtl-mdreloc-arm.c | 124 +++++++- cpukit/libdl/rtl-mdreloc-bfin.c | 29 ++ cpukit/libdl/rtl-mdreloc-h8300.c | 29 ++ cpukit/libdl/rtl-mdreloc-i386.c | 29 ++ cpukit/libdl/rtl-mdreloc-lm32.c | 29 ++ cpukit/libdl/rtl-mdreloc-m68k.c | 29 ++ cpukit/libdl/rtl-mdreloc-mips.c | 29 ++ cpukit/libdl/rtl-mdreloc-moxie.c | 29 ++ cpukit/libdl/rtl-mdreloc-powerpc.c | 44 +++ cpukit/libdl/rtl-mdreloc-sparc.c | 49 ++- cpukit/libdl/rtl-mdreloc-v850.c | 29 ++ cpukit/libdl/rtl-obj.c | 333 +++++++++++++++------ cpukit/libdl/rtl-obj.h | 181 ++++++----- cpukit/libdl/rtl-rap.c | 55 ++-- cpukit/libdl/rtl-rap.h | 7 + cpukit/libdl/rtl-shell.c | 2 +- cpukit/libdl/rtl-unwind-dw2.c | 71 +++++ cpukit/libdl/rtl-unwind-dw2.h | 83 +++++ cpukit/libdl/rtl-unwind.h | 63 ++++ cpukit/libdl/rtl.c | 33 +- cpukit/libdl/rtl.h | 2 +- cpukit/preinstall.am | 4 + 34 files changed, 1239 insertions(+), 259 deletions(-) create mode 100644 cpukit/libdl/rtl-unwind-dw2.c create mode 100644 cpukit/libdl/rtl-unwind-dw2.h create mode 100644 cpukit/libdl/rtl-unwind.h (limited to 'cpukit') diff --git a/cpukit/Makefile.am b/cpukit/Makefile.am index c9a4e0f506..c3f151bd39 100644 --- a/cpukit/Makefile.am +++ b/cpukit/Makefile.am @@ -90,7 +90,7 @@ include_rtems_rtl_HEADERS += libdl/dlfcn-shell.h include_rtems_rtl_HEADERS += libdl/rtl.h libdl/rtl-allocator.h libdl/rtl-obj-fwd.h include_rtems_rtl_HEADERS += libdl/rtl-fwd.h libdl/rtl-obj.h libdl/rtl-obj-cache.h include_rtems_rtl_HEADERS += libdl/rtl-obj-comp.h libdl/rtl-unresolved.h -include_rtems_rtl_HEADERS += libdl/rtl-indirect-ptr.h libdl/rtl-sym.h +include_rtems_rtl_HEADERS += libdl/rtl-indirect-ptr.h libdl/rtl-sym.h libdl/rtl-trace.h include_rtems_rtl_HEADERS += libdl/rap.h libdl/rap-shell.h endif diff --git a/cpukit/libdl/Makefile.am b/cpukit/libdl/Makefile.am index 5c3cd15475..b21c16750a 100644 --- a/cpukit/libdl/Makefile.am +++ b/cpukit/libdl/Makefile.am @@ -25,6 +25,7 @@ libdl_a_SOURCES = \ rtl-string.c \ rtl-sym.c \ rtl-trace.c \ + rtl-unwind-dw2.c \ rtl-unresolved.c libdl_a_SOURCES += rtl-mdreloc-@RTEMS_CPU@.c diff --git a/cpukit/libdl/dlfcn.c b/cpukit/libdl/dlfcn.c index 19feaafd26..3b31bb2e8e 100644 --- a/cpukit/libdl/dlfcn.c +++ b/cpukit/libdl/dlfcn.c @@ -130,7 +130,7 @@ dlerror (void) { static char msg[64]; rtems_rtl_get_error (msg, sizeof (msg)); - return msg; + return msg; } int diff --git a/cpukit/libdl/include/arch/arm/machine/elf_machdep.h b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h index 78c88b5af8..8f01d05212 100644 --- a/cpukit/libdl/include/arch/arm/machine/elf_machdep.h +++ b/cpukit/libdl/include/arch/arm/machine/elf_machdep.h @@ -80,7 +80,8 @@ #define R_ARM_ALU_SBREL_19_12 36 #define R_ARM_ALU_SBREL_27_20 37 #define R_ARM_V4BX 40 -#define R_ARM_PREL31 41 +#define R_ARM_TARGET2 41 +#define R_ARM_PREL31 42 #define R_ARM_MOVW_ABS_NC 43 #define R_ARM_MOVT_ABS 44 diff --git a/cpukit/libdl/include/sys/exec_elf.h b/cpukit/libdl/include/sys/exec_elf.h index 08da7e809e..4242415f54 100644 --- a/cpukit/libdl/include/sys/exec_elf.h +++ b/cpukit/libdl/include/sys/exec_elf.h @@ -459,6 +459,10 @@ typedef struct { #define SHF_WRITE 0x1 /* Section contains writable data */ #define SHF_ALLOC 0x2 /* Section occupies memory */ #define SHF_EXECINSTR 0x4 /* Section contains executable insns */ +#define SHF_MERGE 0x10 /* Section contains data that can be merged */ +#define SHF_STRINGS 0x20 /* Section contains null-terminated strings */ +#define SHF_INFO_LINK 0x40 /* Section header's sh_info holds table index */ +#define SHF_LINK_ORDER 0x80 /* Section has special ordering requirements */ #define SHF_MASKOS 0x0f000000 /* Operating system specific values */ #define SHF_MASKPROC 0xf0000000 /* Processor-specific values */ @@ -949,13 +953,13 @@ typedef struct { #define SYMINFO_NUM 2 /* - * These constants are used for Elf32_Verdef struct's version number. + * These constants are used for Elf32_Verdef struct's version number. */ #define VER_DEF_NONE 0 #define VER_DEF_CURRENT 1 /* - * These constants are used for Elf32_Verdef struct's vd_flags. + * These constants are used for Elf32_Verdef struct's vd_flags. */ #define VER_FLG_BASE 0x1 #define VER_FLG_WEAK 0x2 @@ -967,7 +971,7 @@ typedef struct { #define VER_NDX_GLOBAL 1 /* - * These constants are used for Elf32_Verneed struct's version number. + * These constants are used for Elf32_Verneed struct's version number. */ #define VER_NEED_NONE 0 #define VER_NEED_CURRENT 1 diff --git a/cpukit/libdl/rap.c b/cpukit/libdl/rap.c index 4e07c5472e..87b3bc36e5 100644 --- a/cpukit/libdl/rap.c +++ b/cpukit/libdl/rap.c @@ -19,6 +19,7 @@ #include "config.h" #endif +#include #include #include #include diff --git a/cpukit/libdl/rtl-allocator.c b/cpukit/libdl/rtl-allocator.c index 988094060f..39b4bcd1d0 100644 --- a/cpukit/libdl/rtl-allocator.c +++ b/cpukit/libdl/rtl-allocator.c @@ -152,6 +152,7 @@ rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag, bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** const_base, size_t const_size, + void** eh_base, size_t eh_size, void** data_base, size_t data_size, void** bss_base, size_t bss_size) { @@ -173,7 +174,20 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, const_size, false); if (!*const_base) { - rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); + return false; + } + } + + if (eh_size) + { + *eh_base = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_READ, + eh_size, false); + if (!*eh_base) + { + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); return false; } } @@ -184,7 +198,8 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, data_size, false); if (!*data_base) { - rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); return false; } } @@ -195,7 +210,8 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, bss_size, false); if (!*bss_base) { - rtems_rtl_alloc_module_del (text_base, const_base, data_base, bss_base); + rtems_rtl_alloc_module_del (text_base, const_base, eh_base, + data_base, bss_base); return false; } } @@ -206,12 +222,14 @@ rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void rtems_rtl_alloc_module_del (void** text_base, void** const_base, + void** eh_base, void** data_base, void** bss_base) { rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *bss_base); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_WRITE, *data_base); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *eh_base); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ, *const_base); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_READ_EXEC, *text_base); - *text_base = *const_base = *data_base = *bss_base = NULL; + *text_base = *const_base = *eh_base = *data_base = *bss_base = NULL; } diff --git a/cpukit/libdl/rtl-allocator.h b/cpukit/libdl/rtl-allocator.h index 4d996d3ccd..e8044ee1e8 100644 --- a/cpukit/libdl/rtl-allocator.h +++ b/cpukit/libdl/rtl-allocator.h @@ -146,6 +146,8 @@ void rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag, * @param text_size The size of the read/exec section. * @param const_base Pointer to the const base pointer. * @param const_size The size of the read only section. + * @param eh_base Pointer to the eh base pointer. + * @param eh_size The size of the eh section. * @param data_base Pointer to the data base pointer. * @param data_size The size of the read/write secton. * @param bss_base Pointer to the bss base pointer. @@ -155,6 +157,7 @@ void rtems_rtl_alloc_indirect_del (rtems_rtl_alloc_tag_t tag, */ bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, void** const_base, size_t const_size, + void** eh_base, size_t eh_size, void** data_base, size_t data_size, void** bss_base, size_t bss_size); @@ -163,11 +166,13 @@ bool rtems_rtl_alloc_module_new (void** text_base, size_t text_size, * * @param text_base Pointer to the text base pointer. * @param const_base Pointer to the const base pointer. + * @param eh_base Pointer to the eh base pointer. * @param data_base Pointer to the data base pointer. * @param bss_base Pointer to the bss base pointer. */ void rtems_rtl_alloc_module_del (void** text_base, void** const_base, - void** data_base, void** bss_base); + void** eh_base, void** data_base, + void** bss_base); #ifdef __cplusplus } diff --git a/cpukit/libdl/rtl-debugger.c b/cpukit/libdl/rtl-debugger.c index 63add5956e..afbea8ab44 100644 --- a/cpukit/libdl/rtl-debugger.c +++ b/cpukit/libdl/rtl-debugger.c @@ -45,10 +45,10 @@ _rtld_debug_state (void) int _rtld_linkmap_add (rtems_rtl_obj_t* obj) { - struct link_map* l = (struct link_map*)obj->detail; + struct link_map* l = obj->linkmap; struct link_map* prev; - uint32_t obj_num = obj->obj_num; - int i; + uint32_t obj_num = obj->obj_num; + int i; if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) printf ("rtl: linkmap_add\n"); @@ -78,8 +78,10 @@ _rtld_linkmap_add (rtems_rtl_obj_t* obj) void _rtld_linkmap_delete (rtems_rtl_obj_t* obj) { - struct link_map* l = (struct link_map*)obj->detail; - /* link_maps are allocated together if not 1 */ + struct link_map* l = obj->linkmap; + /* + * link_maps are allocated together if not 1 + */ struct link_map* e = l + obj->obj_num - 1; while (e && e->l_next) e = e->l_next; @@ -90,7 +92,7 @@ _rtld_linkmap_delete (rtems_rtl_obj_t* obj) e->l_next->l_prev = NULL; return; } + if ((l->l_prev->l_next = e->l_next) != NULL) e->l_next->l_prev = l->l_prev; - return; } diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c index b686a4812f..be2f06a7ba 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -30,6 +30,7 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" #include "rtl-unresolved.h" /** @@ -169,6 +170,9 @@ rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj, &relbuf[0], reloc_size)) return false; + /* + * Read the symbol details. + */ if (is_rela) off = (obj->ooffset + symsect->offset + (ELF_R_SYM (rela->r_info) * sizeof (sym))); @@ -246,7 +250,7 @@ rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj, if (is_rela) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rela: sym:%s(%-2d)=%08lx type:%-2d off:%08lx addend:%d\n", + printf ("rtl: rela: sym:%s(%d)=%08lx type:%d off:%08lx addend:%d\n", symname, (int) ELF_R_SYM (rela->r_info), symvalue, (int) ELF_R_TYPE (rela->r_info), rela->r_offset, (int) rela->r_addend); if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect, @@ -256,7 +260,7 @@ rtems_rtl_elf_relocator (rtems_rtl_obj_t* obj, else { if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rel: sym:%s(%-2d)=%08lx type:%-2d off:%08lx\n", + printf ("rtl: rel: sym:%s(%d)=%08lx type:%d off:%08lx\n", symname, (int) ELF_R_SYM (rel->r_info), symvalue, (int) ELF_R_TYPE (rel->r_info), rel->r_offset); if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect, @@ -300,7 +304,7 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc, rela.r_info = reloc->rel[REL_R_INFO]; rela.r_addend = reloc->rel[REL_R_ADDEND]; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rela: sym:%-2d type:%-2d off:%08lx addend:%d\n", + printf ("rtl: rela: sym:%d type:%d off:%08lx addend:%d\n", (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info), rela.r_offset, (int) rela.r_addend); if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect, @@ -313,7 +317,7 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc_t* reloc, rel.r_offset = reloc->rel[REL_R_OFFSET]; rel.r_info = reloc->rel[REL_R_INFO]; if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: rel: sym:%-2d type:%-2d off:%08lx\n", + printf ("rtl: rel: sym:%d type:%d off:%08lx\n", (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info), rel.r_offset); if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect, @@ -652,6 +656,11 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) flags = 0; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) + printf ("rtl: section: %2d: type=%d flags=%08x link=%d info=%d\n", + section, (int) shdr.sh_type, (unsigned int) shdr.sh_flags, + (int) shdr.sh_link, (int) shdr.sh_info); + switch (shdr.sh_type) { case SHT_NULL: @@ -707,9 +716,16 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) break; default: - if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING)) - printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n", - section, (int) shdr.sh_type, (int) shdr.sh_flags); + /* + * See if there are architecture specific flags? + */ + flags = rtems_rtl_elf_section_flags (obj, &shdr); + if (flags == 0) + { + if (rtems_rtl_trace (RTEMS_RTL_TRACE_WARNING)) + printf ("rtl: unsupported section: %2d: type=%02d flags=%02x\n", + section, (int) shdr.sh_type, (int) shdr.sh_flags); + } break; } @@ -718,6 +734,13 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) char* name; size_t len; + /* + * If link ordering this section must appear in the same order in memory + * as the linked-to section relative to the sections it loads with. + */ + if ((shdr.sh_flags & SHF_LINK_ORDER) != 0) + flags |= RTEMS_RTL_OBJ_SECT_LINK; + len = RTEMS_RTL_ELF_STRING_MAX; if (!rtems_rtl_obj_cache_read (strings, fd, sectstroff + shdr.sh_name, @@ -729,6 +752,12 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) if (strcmp (".dtors", name) == 0) flags |= RTEMS_RTL_OBJ_SECT_DTOR; + if (rtems_rtl_elf_unwind_parse (obj, name, flags)) + { + flags &= ~(RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST); + flags |= RTEMS_RTL_OBJ_SECT_EH; + } + if (!rtems_rtl_obj_add_section (obj, section, name, shdr.sh_size, shdr.sh_offset, shdr.sh_addralign, shdr.sh_link, @@ -771,16 +800,19 @@ rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd) return true; } -bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj) +static bool +rtems_rtl_elf_load_linkmap (rtems_rtl_obj_t* obj) { rtems_chain_control* sections = NULL; rtems_chain_node* node = NULL; size_t mask = 0; - struct link_map* l = NULL; int sec_num = 0; + section_detail* sd; int i = 0; - /* caculate the size of sections' name. */ + /* + * Caculate the size of sections' name. + */ for (mask = RTEMS_RTL_OBJ_SECT_TEXT; mask <= RTEMS_RTL_OBJ_SECT_BSS; @@ -791,7 +823,6 @@ bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj) while (!rtems_chain_is_tail (sections, node)) { rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; - if ((sect->size != 0) && ((sect->flags & mask) != 0)) { ++sec_num; @@ -801,32 +832,31 @@ bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj) } obj->obj_num = 1; - obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, - sizeof(struct link_map) + - sec_num * sizeof (section_detail), true); - if (!obj->detail) + obj->linkmap = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, + sizeof(struct link_map) + + sec_num * sizeof (section_detail), true); + if (!obj->linkmap) { - rtems_rtl_set_error (ENOMEM, "no memory for obj global syms"); + rtems_rtl_set_error (ENOMEM, "no memory for obj linkmap"); return false; } - l = (struct link_map*) obj->detail; - l->name = obj->oname; - l->sec_num = sec_num; - l->sec_detail = (section_detail*) (l + 1); - l->rpathlen = 0; - l->rpath = NULL; - l->l_next = NULL; - l->l_prev = NULL; - l->sec_addr[rap_text] = obj->text_base; - l->sec_addr[rap_const] = obj->const_base; - l->sec_addr[rap_data] = obj->data_base; - l->sec_addr[rap_bss] = obj->bss_base; - - - section_detail* sd = l->sec_detail; + obj->linkmap->name = obj->oname; + obj->linkmap->sec_num = sec_num; + obj->linkmap->sec_detail = (section_detail*) (obj->linkmap + 1); + obj->linkmap->rpathlen = 0; + obj->linkmap->rpath = NULL; + obj->linkmap->l_next = NULL; + obj->linkmap->l_prev = NULL; + obj->linkmap->sec_addr[rap_text] = obj->text_base; + obj->linkmap->sec_addr[rap_const] = obj->const_base; + obj->linkmap->sec_addr[rap_data] = obj->data_base; + obj->linkmap->sec_addr[rap_bss] = obj->bss_base; + + sd = obj->linkmap->sec_detail; sections = &obj->sections; node = rtems_chain_first (sections); + for (mask = RTEMS_RTL_OBJ_SECT_TEXT; mask <= RTEMS_RTL_OBJ_SECT_BSS; mask <<= 1) @@ -948,7 +978,12 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd) rtems_rtl_symbol_obj_erase_local (obj); - if (!rtems_rtl_elf_load_details (obj)) + if (!rtems_rtl_elf_load_linkmap (obj)) + { + return false; + } + + if (!rtems_rtl_elf_unwind_register (obj)) { return false; } @@ -956,6 +991,13 @@ rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd) return true; } +bool +rtems_rtl_elf_file_unload (rtems_rtl_obj_t* obj) +{ + rtems_rtl_elf_unwind_deregister (obj); + return true; +} + rtems_rtl_loader_format_t* rtems_rtl_elf_file_sig (void) { diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h index 7f6ea300a3..e3ac07f7ed 100644 --- a/cpukit/libdl/rtl-elf.h +++ b/cpukit/libdl/rtl-elf.h @@ -54,6 +54,18 @@ extern "C" { */ #define RTEMS_RTL_ELF_STRING_MAX (256) +/** + * Architecture specific handler to translate unknown section flags to RTL + * section flags. + * + * @param obj The object file being relocated. + * @param shdr The ELF section header. + * @retval 0 Unknown or unsupported flags. + * @retval uint32_t RTL object file flags. + */ +uint32_t rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr); + /** * Architecture specific handler to check is a relocation record's type is * required to resolve a symbol. @@ -136,13 +148,6 @@ bool rtems_rtl_elf_find_symbol (rtems_rtl_obj_t* obj, */ bool rtems_rtl_elf_file_check (rtems_rtl_obj_t* obj, int fd); -/** - * The ELF file details handler. - * - * @param obj Load the details of the obj. - */ -bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj); - /** * The ELF format load handler. * @@ -151,6 +156,13 @@ bool rtems_rtl_elf_load_details (rtems_rtl_obj_t* obj); */ bool rtems_rtl_elf_file_load (rtems_rtl_obj_t* obj, int fd); +/** + * The ELF format unload handler. + * + * @param obj The object to unload. + */ +bool rtems_rtl_elf_file_unload (rtems_rtl_obj_t* obj); + /** * The ELF format signature handler. * diff --git a/cpukit/libdl/rtl-error.c b/cpukit/libdl/rtl-error.c index 3251fa5392..5ec4b26ef7 100644 --- a/cpukit/libdl/rtl-error.c +++ b/cpukit/libdl/rtl-error.c @@ -17,6 +17,7 @@ #include "config.h" #endif +#include #include #include @@ -39,9 +40,15 @@ int rtems_rtl_get_error (char* message, size_t max_message) { rtems_rtl_data_t* rtl = rtems_rtl_lock (); - int last_errno = rtl->last_errno; - strncpy (message, rtl->last_error, sizeof (rtl->last_error)); - rtems_rtl_unlock (); - return last_errno; -} + if (rtl != NULL) + { + int last_errno = rtl->last_errno; + strncpy (message, rtl->last_error, sizeof (rtl->last_error)); + rtems_rtl_unlock (); + return last_errno; + } + strncpy(message, "RTL init error", max_message); + + return EIO; +} diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c index 692c8297a8..f2f91f171c 100644 --- a/cpukit/libdl/rtl-mdreloc-arm.c +++ b/cpukit/libdl/rtl-mdreloc-arm.c @@ -10,11 +10,14 @@ #include #include #include +#include +#include #include #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" /* * It is possible for the compiler to emit relocations for unaligned data. @@ -23,6 +26,8 @@ #define RELOC_ALIGNED_P(x) \ (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) +#define SHT_ARM_EXIDX 0x70000001 /* Section holds ARM unwind info. */ + static inline Elf_Addr load_ptr(void *where) { @@ -52,6 +57,24 @@ isThumb(Elf_Word symvalue) else return false; } +static inline Elf_SOff +sign_extend31(Elf_Addr val) +{ + if (0x40000000 & val) + val = ~((Elf_Addr)0x7fffffff) | (0x7fffffff & val); + return 0x7fffffff & val; +} + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + uint32_t flags = 0; + if (shdr->sh_type == SHT_ARM_EXIDX) + flags = RTEMS_RTL_OBJ_SECT_EH | RTEMS_RTL_OBJ_SECT_LOAD; + return flags; +} + bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { @@ -87,8 +110,11 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, where = (Elf_Addr *)(sect->base + rel->r_offset); switch (ELF_R_TYPE(rel->r_info)) { - case R_TYPE(NONE): - break; + case R_TYPE(NONE): + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) { + printf ("rtl: NONE %p in %s\n", where, rtems_rtl_obj_oname (obj)); + } + break; case R_TYPE(CALL): /* BL/BLX */ case R_TYPE(JUMP24): /* B/BL */ @@ -165,24 +191,32 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, case R_TYPE(REL32): /* word32 (S + A) | T - P */ case R_TYPE(ABS32): /* word32 (S + A) | T */ case R_TYPE(GLOB_DAT): /* word32 (S + A) | T */ + case R_TYPE(PREL31): /* word32 (S + A) | T - P */ + case R_TYPE(TARGET2): /* Equivalent to REL32 */ if (__predict_true(RELOC_ALIGNED_P(where))) { tmp = *where + symvalue; if (isThumb(symvalue)) tmp |= 1; - if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32)) + if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) || + ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2)) tmp -= (Elf_Addr)where; + else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31)) + tmp = sign_extend31(tmp - (Elf_Addr)where); *where = tmp; } else { tmp = load_ptr(where) + symvalue; if (isThumb(symvalue)) tmp |= 1; - if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32)) + if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) || + ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2)) tmp -= (Elf_Addr)where; + else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31)) + tmp = sign_extend31(tmp - (Elf_Addr)where); store_ptr(where, tmp); } if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) - printf ("rtl: REL32/ABS32/GLOB_DAT %p @ %p in %s", + printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s\n", (void *)tmp, where, rtems_rtl_obj_oname (obj)); break; @@ -306,7 +340,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, (void *)*where, where, rtems_rtl_obj_oname (obj)); break; - default: + default: printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " "contents = %p\n", ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info), @@ -315,9 +349,83 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, "%s: Unsupported relocation type %ld " "in non-PLT relocations", sect->name, (uint32_t) ELF_R_TYPE(rel->r_info)); - return false; + return false; } - return true; + return true; +} + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + /* + * We location the EH sections in section flags. + */ + return false; } +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return true; +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + obj->loader = NULL; + return true; +} + +/* An exception index table entry. */ +typedef struct __EIT_entry +{ + _uw fnoffset; + _uw content; +} __EIT_entry; + +/* The exception index table location in the base module */ +extern __EIT_entry __exidx_start; +extern __EIT_entry __exidx_end; + +/* + * A weak reference is in libgcc, provide a real version and provide a way to + * manage loaded modules. + * + * Passed in the return address and a reference to the number of records + * found. We set the start of the exidx data and the number of records. + */ +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr return_address, + int* nrec) __attribute__ ((__noinline__, + __used__, + __noclone__)); + +_Unwind_Ptr __gnu_Unwind_Find_exidx (_Unwind_Ptr return_address, + int* nrec) +{ + rtems_rtl_data_t* rtl; + rtems_chain_node* node; + __EIT_entry* exidx_start = &__exidx_start; + __EIT_entry* exidx_end = &__exidx_end; + + rtl = rtems_rtl_lock (); + + node = rtems_chain_first (&rtl->objects); + while (!rtems_chain_is_tail (&rtl->objects, node)) { + rtems_rtl_obj_t* obj = (rtems_rtl_obj_t*) node; + if (rtems_rtl_obj_text_inside (obj, (void*) return_address)) { + exidx_start = (__EIT_entry*) obj->eh_base; + exidx_end = (__EIT_entry*) (obj->eh_base + obj->eh_size); + break; + } + node = rtems_chain_next (node); + } + + rtems_rtl_unlock (); + + *nrec = exidx_end - exidx_start; + + return (_Unwind_Ptr) exidx_start; +} diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c index d855d3061e..5a1fd26e3c 100644 --- a/cpukit/libdl/rtl-mdreloc-bfin.c +++ b/cpukit/libdl/rtl-mdreloc-bfin.c @@ -6,6 +6,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -113,3 +122,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rel type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c index 925601b7d2..0ef717bfb3 100644 --- a/cpukit/libdl/rtl-mdreloc-h8300.c +++ b/cpukit/libdl/rtl-mdreloc-h8300.c @@ -9,6 +9,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -99,3 +108,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rel type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c index b6dd9b7306..c8f1e11c3e 100644 --- a/cpukit/libdl/rtl-mdreloc-i386.c +++ b/cpukit/libdl/rtl-mdreloc-i386.c @@ -15,6 +15,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -101,3 +110,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, return true; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c index 057d6ce6dd..e7e2a4c9c5 100644 --- a/cpukit/libdl/rtl-mdreloc-lm32.c +++ b/cpukit/libdl/rtl-mdreloc-lm32.c @@ -9,6 +9,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -118,3 +127,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rela type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c index 36692ebf85..8a91ebcc44 100644 --- a/cpukit/libdl/rtl-mdreloc-m68k.c +++ b/cpukit/libdl/rtl-mdreloc-m68k.c @@ -15,6 +15,8 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" static inline int overflow_8_check(int value) { @@ -30,6 +32,13 @@ static inline int overflow_16_check(int value) return false; } +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} + bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { @@ -146,3 +155,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rel type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c index c17dbc2ee2..7ceac54765 100644 --- a/cpukit/libdl/rtl-mdreloc-mips.c +++ b/cpukit/libdl/rtl-mdreloc-mips.c @@ -9,6 +9,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -188,3 +197,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, return true; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c index 1fb05e6977..27b0cf6824 100644 --- a/cpukit/libdl/rtl-mdreloc-moxie.c +++ b/cpukit/libdl/rtl-mdreloc-moxie.c @@ -10,6 +10,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -86,3 +95,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rel type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c index 6909167704..978a2e8999 100644 --- a/cpukit/libdl/rtl-mdreloc-powerpc.c +++ b/cpukit/libdl/rtl-mdreloc-powerpc.c @@ -15,11 +15,19 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" #define ha(x) ((((u_int32_t)(x) & 0x8000) ? \ ((u_int32_t)(x) + 0x10000) : (u_int32_t)(x)) >> 16) #define l(x) ((u_int32_t)(x) & 0xffff) +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -158,6 +166,22 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj, (void *)*where, where, rtems_rtl_obj_oname (obj)); break; + case R_TYPE(SDAREL16): + /* + * A sign-extended 16 bit value relative to _SDA_BASE_, for use with + * small data items. + */ + mask = 0xffff; + tmp = *((Elf32_Half*) where); + tmp &= ~mask; + tmp |= (symvalue + rela->r_addend - (Elf_Addr)where) & mask; + *((Elf32_Half*) where) = tmp; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) + printf ("rtl: SDAREL16 %p @ %p in %s\n", + (void *) (uintptr_t) *((Elf32_Half*) where), + where, rtems_rtl_obj_oname (obj)); + break; + default: printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, " "contents = %p\n", @@ -183,3 +207,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, printf ("rtl: rel type record not supported; please report\n"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c index a8bf5e15ae..8d1239421d 100644 --- a/cpukit/libdl/rtl-mdreloc-sparc.c +++ b/cpukit/libdl/rtl-mdreloc-sparc.c @@ -41,6 +41,8 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" /* * The following table holds for each relocation type: @@ -128,6 +130,13 @@ static const int reloc_target_bitmask[] = { }; #define RELOC_VALUE_BITMASK(t) (reloc_target_bitmask[t]) +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} + bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) { @@ -144,6 +153,7 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj, { Elf_Addr *where; Elf_Word type, value, mask; + Elf_Addr tmp = 0; where = (Elf_Addr *) (sect->base + rela->r_offset); @@ -219,31 +229,32 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj, value &= mask; if (RELOC_UNALIGNED(type)) { - /* Handle unaligned relocations. */ - Elf_Addr tmp = 0; - char *ptr = (char *)where; + /* + * Handle unaligned relocations. + */ + char *ptr = (char*) where; int i, size = RELOC_TARGET_SIZE (type) / 8; /* Read it in one byte at a time. */ - for (i=0; i= 0; i--) tmp = (tmp << 8) | ptr[i]; tmp &= ~mask; tmp |= value; /* Write it back out. */ - for (i=0; i> (8*i)) & 0xff); - + for (i = size - 1; i >= 0; i--, tmp >>= 8) + ptr[i] = tmp & 0xff; } else { *where &= ~mask; *where |= value; + tmp = *where; } if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf ("rtl: %s %p @ %p in %s\n", - reloc_names[type], (void *)*where, where, rtems_rtl_obj_oname (obj)); - + reloc_names[ELF_R_TYPE(rela->r_info)], + (void *)tmp, where, rtems_rtl_obj_oname (obj)); return true; } @@ -259,3 +270,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, printf ("rtl: rel type record not supported; please report\n"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c index 5372e81e8d..7f958a5fb8 100644 --- a/cpukit/libdl/rtl-mdreloc-v850.c +++ b/cpukit/libdl/rtl-mdreloc-v850.c @@ -10,6 +10,15 @@ #include "rtl-elf.h" #include "rtl-error.h" #include "rtl-trace.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +uint32_t +rtems_rtl_elf_section_flags (const rtems_rtl_obj_t* obj, + const Elf_Shdr* shdr) +{ + return 0; +} bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type) @@ -95,3 +104,23 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj_t* obj, rtems_rtl_set_error (EINVAL, "rel type record not supported"); return false; } + +bool +rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return rtems_rtl_elf_unwind_dw2_parse (obj, name, flags); +} + +bool +rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_register (obj); +} + +bool +rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj) +{ + return rtems_rtl_elf_unwind_dw2_deregister (obj); +} diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index bdcebce61e..bb0bc8d543 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -49,14 +49,21 @@ /** * The table of supported loader formats. */ -static rtems_rtl_loader_table_t loaders[RTEMS_RTL_ELF_LOADER_COUNT + - RTEMS_RTL_RAP_LOADER_COUNT] = +#define RTEMS_RTL_LOADERS (RTEMS_RTL_ELF_LOADER_COUNT + RTEMS_RTL_RAP_LOADER_COUNT) +static const rtems_rtl_loader_table_t loaders[RTEMS_RTL_LOADERS] = { #if RTEMS_RTL_RAP_LOADER - { rtems_rtl_rap_file_check, rtems_rtl_rap_file_load, rtems_rtl_rap_file_sig }, + { .check = rtems_rtl_rap_file_check, + .load = rtems_rtl_rap_file_load, + .unload = rtems_rtl_rap_file_unload, + .unload = rtems_rtl_rap_file_unload, + .signature = rtems_rtl_rap_file_sig }, #endif #if RTEMS_RTL_ELF_LOADER - { rtems_rtl_elf_file_check, rtems_rtl_elf_file_load, rtems_rtl_elf_file_sig }, + { .check = rtems_rtl_elf_file_check, + .load = rtems_rtl_elf_file_load, + .unload = rtems_rtl_elf_file_unload, + .signature = rtems_rtl_elf_file_sig }, #endif }; @@ -72,6 +79,10 @@ rtems_rtl_obj_alloc (void) * Initialise the chains. */ rtems_chain_initialize_empty (&obj->sections); + /* + * No valid format. + */ + obj->format = -1; } return obj; } @@ -97,14 +108,14 @@ rtems_rtl_obj_free (rtems_rtl_obj_t* obj) } if (!rtems_chain_is_node_off_chain (&obj->link)) rtems_chain_extract (&obj->link); - rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, + rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base, &obj->data_base, &obj->bss_base); rtems_rtl_symbol_obj_erase (obj); rtems_rtl_obj_free_names (obj); if (obj->sec_num) free (obj->sec_num); - if (obj->detail) - rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*)obj->detail); + if (obj->linkmap) + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) obj->linkmap); rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj); return true; } @@ -238,7 +249,7 @@ rtems_rtl_scan_decimal (const uint8_t* string, size_t len) static size_t rtems_rtl_sect_align (size_t offset, uint32_t alignment) { - if ((alignment > 1) && ((offset & ~alignment) != 0)) + if ((alignment > 1) && ((offset & (alignment - 1)) != 0)) offset = (offset + alignment) & ~(alignment - 1); return offset; } @@ -264,12 +275,12 @@ rtems_rtl_obj_sect_summer (rtems_chain_node* node, void* data) } static size_t -rtems_rtl_obj_section_size (rtems_rtl_obj_t* obj, uint32_t mask) +rtems_rtl_obj_section_size (const rtems_rtl_obj_t* obj, uint32_t mask) { rtems_rtl_obj_sect_summer_t summer; summer.mask = mask; summer.size = 0; - rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections, rtems_rtl_obj_sect_summer, &summer); return summer.size; @@ -302,12 +313,12 @@ rtems_rtl_obj_sect_aligner (rtems_chain_node* node, void* data) } static size_t -rtems_rtl_obj_section_alignment (rtems_rtl_obj_t* obj, uint32_t mask) +rtems_rtl_obj_section_alignment (const rtems_rtl_obj_t* obj, uint32_t mask) { rtems_rtl_obj_sect_aligner_t aligner; aligner.mask = mask; aligner.alignment = 0; - rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections, rtems_rtl_obj_sect_aligner, &aligner); return aligner.alignment; @@ -401,26 +412,30 @@ rtems_rtl_obj_add_section (rtems_rtl_obj_t* obj, int info, uint32_t flags) { - rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, - sizeof (rtems_rtl_obj_sect_t), true); - if (!sect) + if (size > 0) { - rtems_rtl_set_error (ENOMEM, "adding allocated section"); - return false; + rtems_rtl_obj_sect_t* sect = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, + sizeof (rtems_rtl_obj_sect_t), + true); + if (!sect) + { + rtems_rtl_set_error (ENOMEM, "adding allocated section"); + return false; + } + sect->section = section; + sect->name = rtems_rtl_strdup (name); + sect->size = size; + sect->offset = offset; + sect->alignment = alignment; + sect->link = link; + sect->info = info; + sect->flags = flags; + sect->base = NULL; + rtems_chain_append (&obj->sections, §->node); + + if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION)) + printf ("rtl: sect: %-2d: %s (%zu)\n", section, name, size); } - sect->section = section; - sect->name = rtems_rtl_strdup (name); - sect->size = size; - sect->offset = offset; - sect->alignment = alignment; - sect->link = link; - sect->info = info; - sect->flags = flags; - sect->base = NULL; - rtems_chain_append (&obj->sections, §->node); - - if (rtems_rtl_trace (RTEMS_RTL_TRACE_SECTION)) - printf ("rtl: sect: %-2d: %s\n", section, name); return true; } @@ -464,12 +479,13 @@ rtems_rtl_obj_sect_match_name (rtems_chain_node* node, void* data) } rtems_rtl_obj_sect_t* -rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, const char* name) +rtems_rtl_obj_find_section (const rtems_rtl_obj_t* obj, + const char* name) { rtems_rtl_obj_sect_finder_t match; match.sect = NULL; match.name = name; - rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections, rtems_rtl_obj_sect_match_name, &match); return match.sect; @@ -489,61 +505,74 @@ rtems_rtl_obj_sect_match_index (rtems_chain_node* node, void* data) } rtems_rtl_obj_sect_t* -rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, int index) +rtems_rtl_obj_find_section_by_index (const rtems_rtl_obj_t* obj, + int index) { rtems_rtl_obj_sect_finder_t match; match.sect = NULL; match.index = index; - rtems_rtl_chain_iterate (&obj->sections, + rtems_rtl_chain_iterate ((rtems_chain_control*) &obj->sections, rtems_rtl_obj_sect_match_index, &match); return match.sect; } size_t -rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj) +rtems_rtl_obj_text_size (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT); } uint32_t -rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj) +rtems_rtl_obj_text_alignment (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT); } size_t -rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj) +rtems_rtl_obj_const_size (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST); } uint32_t -rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj) +rtems_rtl_obj_eh_alignment (const rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_EH); +} + +size_t +rtems_rtl_obj_eh_size (const rtems_rtl_obj_t* obj) +{ + return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_EH); +} + +uint32_t +rtems_rtl_obj_const_alignment (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST); } size_t -rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj) +rtems_rtl_obj_data_size (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA); } uint32_t -rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj) +rtems_rtl_obj_data_alignment (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA); } size_t -rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj) +rtems_rtl_obj_bss_size (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_BSS); } uint32_t -rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj) +rtems_rtl_obj_bss_alignment (const rtems_rtl_obj_t* obj) { return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_BSS); } @@ -572,21 +601,25 @@ typedef struct static bool rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data) { - rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; rtems_rtl_obj_sect_sync_ctx_t* sync_ctx = data; - uintptr_t old_end; - uintptr_t new_start; + uintptr_t old_end; + uintptr_t new_start; - if ( !(sect->flags & sync_ctx->mask) || !sect->size) + if ((sect->flags & sync_ctx->mask) == 0 || sect->size == 0) return true; - if (sync_ctx->end_va == sync_ctx->start_va) { + if (sync_ctx->end_va == sync_ctx->start_va) + { sync_ctx->start_va = sect->base; - } else { - old_end = (uintptr_t)sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1); - new_start = (uintptr_t)sect->base & ~(sync_ctx->cache_line_size - 1); - if ( (sect->base < sync_ctx->start_va) || - (new_start - old_end > sync_ctx->cache_line_size) ) { + } + else + { + old_end = (uintptr_t) sync_ctx->end_va & ~(sync_ctx->cache_line_size - 1); + new_start = (uintptr_t) sect->base & ~(sync_ctx->cache_line_size - 1); + if ((sect->base < sync_ctx->start_va) || + (new_start - old_end > sync_ctx->cache_line_size)) + { rtems_cache_instruction_sync_after_code_change(sync_ctx->start_va, sync_ctx->end_va - sync_ctx->start_va + 1); sync_ctx->start_va = sect->base; @@ -599,7 +632,7 @@ rtems_rtl_obj_sect_sync_handler (rtems_chain_node* node, void* data) } void -rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t* obj) +rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t* obj) { rtems_rtl_obj_sect_sync_ctx_t sync_ctx; @@ -610,7 +643,7 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj_t* obj) sync_ctx.mask = RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_BSS | - RTEMS_RTL_OBJ_SECT_EXEC; + RTEMS_RTL_OBJ_SECT_EH | RTEMS_RTL_OBJ_SECT_EXEC; sync_ctx.start_va = 0; sync_ctx.end_va = sync_ctx.start_va; @@ -634,6 +667,87 @@ rtems_rtl_obj_load_symbols (rtems_rtl_obj_t* obj, return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data); } +static int +rtems_rtl_obj_sections_linked_to_order (rtems_rtl_obj_t* obj, + int section, + uint32_t visited_mask) +{ + rtems_chain_control* sections = &obj->sections; + rtems_chain_node* node = rtems_chain_first (sections); + /* + * Find the section being linked-to. If the linked-to link field is 0 we have + * the end and the section's order is the position we are after. + */ + while (!rtems_chain_is_tail (sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + if (sect->section == section) + { + const uint32_t mask = sect->flags & RTEMS_RTL_OBJ_SECT_TYPES; + int order = 0; + if (sect->link != 0) + { + /* + * Have we already visited this type of section? Avoid nesting for + * ever. + */ + if ((sect->flags & visited_mask) != 0) + { + rtems_rtl_set_error (errno, "section link loop"); + return -1; + } + return rtems_rtl_obj_sections_linked_to_order (obj, + sect->link, + visited_mask | mask); + } + node = rtems_chain_first (sections); + while (!rtems_chain_is_tail (sections, node)) + { + sect = (rtems_rtl_obj_sect_t*) node; + if ((sect->flags & mask) == mask) + { + if (sect->section == section) + return order; + ++order; + } + node = rtems_chain_next (node); + } + } + node = rtems_chain_next (node); + } + rtems_rtl_set_error (errno, "section link not found"); + return -1; +} + +static void +rtems_rtl_obj_sections_link_order (uint32_t mask, rtems_rtl_obj_t* obj) +{ + rtems_chain_control* sections = &obj->sections; + rtems_chain_node* node = rtems_chain_first (sections); + int order = 0; + while (!rtems_chain_is_tail (sections, node)) + { + rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; + if ((sect->flags & mask) == mask) + { + /* + * If the section is linked in order find the linked-to section's order + * and move the section in the section list to + */ + if (sect->link == 0) + sect->load_order = order++; + else + { + sect->load_order = + rtems_rtl_obj_sections_linked_to_order (obj, + sect->link, + mask); + } + } + node = rtems_chain_next (node); + } +} + static size_t rtems_rtl_obj_sections_loader (uint32_t mask, rtems_rtl_obj_t* obj, @@ -646,42 +760,54 @@ rtems_rtl_obj_sections_loader (uint32_t mask, rtems_chain_node* node = rtems_chain_first (sections); size_t base_offset = 0; bool first = true; + int order = 0; + while (!rtems_chain_is_tail (sections, node)) { rtems_rtl_obj_sect_t* sect = (rtems_rtl_obj_sect_t*) node; if ((sect->size != 0) && ((sect->flags & mask) != 0)) { - if (!first) - base_offset = rtems_rtl_sect_align (base_offset, sect->alignment); + if (sect->load_order == order) + { + if (!first) + base_offset = rtems_rtl_sect_align (base_offset, sect->alignment); - sect->base = base + base_offset; + first = false; - if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) - printf ("rtl: loading: %s -> %8p (%zi)\n", - sect->name, sect->base, sect->size); + sect->base = base + base_offset; - if ((sect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == RTEMS_RTL_OBJ_SECT_LOAD) - { - if (!handler (obj, fd, sect, data)) + if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) + printf ("rtl: loading:%2d: %s -> %8p (s:%zi f:%04lx a:%lu 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; + return false; + } + } + else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO) + { + memset (base + base_offset, 0, sect->size); + } + else { sect->base = 0; + rtems_rtl_set_error (errno, "section has no load/clear op"); return false; } - } - else if ((sect->flags & RTEMS_RTL_OBJ_SECT_ZERO) == RTEMS_RTL_OBJ_SECT_ZERO) - { - memset (base + base_offset, 0, sect->size); - } - else - { - sect->base = 0; - rtems_rtl_set_error (errno, "section has no load op"); - return false; - } - base_offset += sect->size; - first = false; + base_offset += sect->size; + + ++order; + + node = rtems_chain_first (sections); + continue; + } } node = rtems_chain_next (node); @@ -698,20 +824,30 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, { size_t text_size; size_t const_size; + size_t eh_size; size_t data_size; size_t bss_size; text_size = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj); - const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_data_alignment (obj); + const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj); + eh_size = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj); data_size = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj); bss_size = rtems_rtl_obj_bss_size (obj); + /* + * Set the sizes held in the object data. We need this for a fast reference. + */ + obj->text_size = text_size; + obj->eh_size = eh_size; + obj->bss_size = bss_size; + /* * Let the allocator manage the actual allocation. The user can use the * standard heap or provide a specific allocator with memory protection. */ if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size, &obj->const_base, const_size, + &obj->eh_base, eh_size, &obj->data_base, data_size, &obj->bss_base, bss_size)) { @@ -720,7 +856,7 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, return false; } - obj->exec_size = text_size + const_size + data_size + bss_size; + obj->exec_size = text_size + const_size + eh_size + data_size + bss_size; if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT)) { @@ -728,12 +864,22 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj)); printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n", obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj)); + printf ("rtl: load sect: eh - b:%p s:%zi a:%" PRIu32 "\n", + obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj)); printf ("rtl: load sect: data - b:%p s:%zi a:%" PRIu32 "\n", obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj)); printf ("rtl: load sect: bss - b:%p s:%zi a:%" PRIu32 "\n", obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj)); } + /* + * Determine the load order. + */ + rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_TEXT, obj); + rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj); + rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH, obj); + rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA, obj); + /* * Load all text then data then bss sections in seperate operations so each * type of section is grouped together. @@ -742,12 +888,14 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* obj, obj, fd, obj->text_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_CONST, obj, fd, obj->const_base, handler, data) || + !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_EH, + obj, fd, obj->eh_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_DATA, obj, fd, obj->data_base, handler, data) || !rtems_rtl_obj_sections_loader (RTEMS_RTL_OBJ_SECT_BSS, obj, fd, obj->bss_base, handler, data)) { - rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, + rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base, &obj->data_base, &obj->bss_base); obj->exec_size = 0; return false; @@ -972,7 +1120,7 @@ rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd) * name from the table and compare with the name we are after. */ #define RTEMS_RTL_MAX_FILE_SIZE (256) - char name[RTEMS_RTL_MAX_FILE_SIZE]; + char name[RTEMS_RTL_MAX_FILE_SIZE]; if (!rtems_rtl_seek_read (fd, extended_file_names + extended_off, RTEMS_RTL_MAX_FILE_SIZE, (uint8_t*) &name[0])) @@ -1016,7 +1164,7 @@ rtems_rtl_obj_archive_find (rtems_rtl_obj_t* obj, int fd) return false; } -bool +static bool rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd) { int l; @@ -1024,13 +1172,24 @@ rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd) for (l = 0; l < (sizeof (loaders) / sizeof (rtems_rtl_loader_table_t)); ++l) { if (loaders[l].check (obj, fd)) + { + obj->format = l; return loaders[l].load (obj, fd); + } } rtems_rtl_set_error (ENOENT, "no format loader found"); return false; } +static bool +rtems_rtl_obj_file_unload (rtems_rtl_obj_t* obj) +{ + if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS) + return loaders[obj->format].unload (obj); + return false; +} + bool rtems_rtl_obj_load (rtems_rtl_obj_t* obj) { @@ -1057,20 +1216,16 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj) { if (!rtems_rtl_obj_archive_find (obj, fd)) { - rtems_rtl_obj_caches_flush (); close (fd); return false; } } /* - * Call the format specific loader. Currently this is a call to the ELF - * loader. This call could be changed to allow probes then calls if more than - * one format is supported. + * Call the format specific loader. */ if (!rtems_rtl_obj_file_load (obj, fd)) { - rtems_rtl_obj_caches_flush (); close (fd); return false; } @@ -1081,8 +1236,6 @@ rtems_rtl_obj_load (rtems_rtl_obj_t* obj) return false; } - rtems_rtl_obj_caches_flush (); - close (fd); return true; @@ -1092,6 +1245,6 @@ bool rtems_rtl_obj_unload (rtems_rtl_obj_t* obj) { _rtld_linkmap_delete(obj); - rtems_rtl_symbol_obj_erase (obj); - return rtems_rtl_obj_free (obj); + rtems_rtl_obj_file_unload (obj); + return true; } diff --git a/cpukit/libdl/rtl-obj.h b/cpukit/libdl/rtl-obj.h index 80fc60fb05..6a35a72822 100644 --- a/cpukit/libdl/rtl-obj.h +++ b/cpukit/libdl/rtl-obj.h @@ -56,14 +56,20 @@ typedef struct rtems_rtl_loader_format_s typedef bool (*rtems_rtl_loader_check) (rtems_rtl_obj_t* obj, int fd); /** - * The type of the format loader handler. This handler loads the specific + * The type of the format loader load handler. This handler loads the specific * format. */ typedef bool (*rtems_rtl_loader_load) (rtems_rtl_obj_t* obj, int fd); /** - * The type of the format loader handler. This handler loads the specific - * format. + * The type of the format loader unload handler. This handler unloads the + * specific format. + */ +typedef bool (*rtems_rtl_loader_unload) (rtems_rtl_obj_t* obj); + +/** + * The type of the format loader signature handler. This handler checks the + * format signature. */ typedef rtems_rtl_loader_format_t* (*rtems_rtl_loader_sig) (void); @@ -72,9 +78,10 @@ typedef rtems_rtl_loader_format_t* (*rtems_rtl_loader_sig) (void); */ typedef struct rtems_rtl_loader_table_s { - rtems_rtl_loader_check check; /**< The check handler. */ - rtems_rtl_loader_load load; /**< The loader. */ - rtems_rtl_loader_sig signature; /**< The loader's signature. */ + rtems_rtl_loader_check check; /**< The check handler. */ + rtems_rtl_loader_load load; /**< The loader. */ + rtems_rtl_loader_unload unload; /**< The unloader. */ + rtems_rtl_loader_sig signature; /**< The loader's signature. */ } rtems_rtl_loader_table_t; /** @@ -84,18 +91,30 @@ typedef struct rtems_rtl_loader_table_s #define RTEMS_RTL_OBJ_SECT_CONST (1 << 1) /**< Section holds program text. */ #define RTEMS_RTL_OBJ_SECT_DATA (1 << 2) /**< Section holds program data. */ #define RTEMS_RTL_OBJ_SECT_BSS (1 << 3) /**< Section holds program bss. */ -#define RTEMS_RTL_OBJ_SECT_REL (1 << 4) /**< Section holds relocation records. */ -#define RTEMS_RTL_OBJ_SECT_RELA (1 << 5) /**< Section holds relocation addend +#define RTEMS_RTL_OBJ_SECT_EH (1 << 4) /**< Section holds exception data. */ +#define RTEMS_RTL_OBJ_SECT_REL (1 << 5) /**< Section holds relocation records. */ +#define RTEMS_RTL_OBJ_SECT_RELA (1 << 6) /**< Section holds relocation addend * records. */ -#define RTEMS_RTL_OBJ_SECT_SYM (1 << 6) /**< Section holds symbols. */ -#define RTEMS_RTL_OBJ_SECT_STR (1 << 7) /**< Section holds strings. */ -#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 8) /**< Section allocates runtime memory. */ -#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 9) /**< Section is loaded from object file. */ -#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 10) /**< Section is writable, ie data. */ -#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 11) /**< Section is executable. */ -#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 12) /**< Section is preset to zero. */ -#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 13) /**< Section contains constructors. */ -#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 14) /**< Section contains destructors. */ +#define RTEMS_RTL_OBJ_SECT_SYM (1 << 7) /**< Section holds symbols. */ +#define RTEMS_RTL_OBJ_SECT_STR (1 << 8) /**< Section holds strings. */ +#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 9) /**< Section allocates runtime memory. */ +#define RTEMS_RTL_OBJ_SECT_LOAD (1 << 10) /**< Section is loaded from object file. */ +#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 11) /**< Section is writable, ie data. */ +#define RTEMS_RTL_OBJ_SECT_EXEC (1 << 12) /**< Section is executable. */ +#define RTEMS_RTL_OBJ_SECT_ZERO (1 << 13) /**< Section is preset to zero. */ +#define RTEMS_RTL_OBJ_SECT_LINK (1 << 14) /**< Section is link-ordered. */ +#define RTEMS_RTL_OBJ_SECT_CTOR (1 << 15) /**< Section contains constructors. */ +#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 16) /**< Section contains destructors. */ +#define RTEMS_RTL_OBJ_SECT_LOCD (1 << 17) /**< Section has been located. */ + +/** + * Section types mask. + */ +#define RTEMS_RTL_OBJ_SECT_TYPES (RTEMS_RTL_OBJ_SECT_TEXT | \ + RTEMS_RTL_OBJ_SECT_CONST | \ + RTEMS_RTL_OBJ_SECT_DATA | \ + RTEMS_RTL_OBJ_SECT_BSS | \ + RTEMS_RTL_OBJ_SECT_EH) /** * An object file is made up of sections and the can be more than @@ -109,13 +128,14 @@ struct rtems_rtl_obj_sect_s const char* name; /**< The section's name. */ size_t size; /**< The size of the section in memory. */ off_t offset; /**< Offset into the object file. Relative to - * the start of the object file. */ + * the start of the object file. */ uint32_t alignment; /**< Alignment of this section. */ int link; /**< Section link field. */ int info; /**< Secfion info field. */ uint32_t flags; /**< The section's flags. */ void* base; /**< The base address of the section in * memory. */ + int load_order; /**< Order we load sections. */ }; /** @@ -135,6 +155,7 @@ struct rtems_rtl_obj_s rtems_chain_node link; /**< The node's link in the chain. */ uint32_t flags; /**< The status of the object file. */ uint32_t users; /**< References to the object file. */ + int format; /**< The format of the object file. */ const char* fname; /**< The file name for the object. */ const char* oname; /**< The object file name. Can be * relative. */ @@ -153,26 +174,27 @@ struct rtems_rtl_obj_s size_t global_size; /**< Global symbol memory usage. */ uint32_t unresolved; /**< The number of unresolved relocations. */ void* text_base; /**< The base address of the text section - * in memory. */ + * in memory. */ + size_t text_size; /**< The size of the text section. */ void* const_base; /**< The base address of the const section - * in memory. */ + * in memory. */ + void* eh_base; /**< The base address of the eh section + * in memory. */ + size_t eh_size; /**< The size of the eh section. */ void* data_base; /**< The base address of the data section - * in memory. */ + * in memory. */ void* bss_base; /**< The base address of the bss section - * in memory. */ + * in memory. */ size_t bss_size; /**< The size of the bss section. */ size_t exec_size; /**< The amount of executable memory - * allocated */ + * allocated */ void* entry; /**< The entry point of the module. */ uint32_t checksum; /**< The checksum of the text sections. A - * zero means do not checksum. */ - void* detail; /**< The file details. It contains the elf file - * detail, mainly including elf file name, - * section offset, section size, which - * elf this section belongs to.*/ + * zero means do not checksum. */ uint32_t* sec_num; /**< The sec nums of each obj. */ uint32_t obj_num; /**< The count of elf files in an rtl obj. */ struct link_map* linkmap; /**< For GDB. */ + void* loader; /**< The file details specific to a loader. */ }; /** @@ -257,6 +279,20 @@ static inline bool rtems_rtl_obj_aname_valid (const rtems_rtl_obj_t* obj) return obj->aname; } +/** + * Is the address inside the text section? + * + * @param obj The object file. + * @return bool There is an archive name + */ +static inline bool rtems_rtl_obj_text_inside (const rtems_rtl_obj_t* obj, + const void* address) +{ + return + (address >= obj->text_base) && + (address < (obj->text_base + obj->text_size)); +} + /** * Allocate an object structure on the heap. * @@ -299,18 +335,6 @@ bool rtems_rtl_parse_name (const char* name, const char** oname, off_t* ooffset); -/** - * Load the object file. - * - * @param obj The object file's descriptor. - * @param fd The file descriptor. - * @param load_syms Load symbols. - * @param load_dep Load dependent object files. - * @retval true The load was successful. - * @retval false The load failed. The RTL error has been set. - */ -bool rtems_rtl_obj_file_load (rtems_rtl_obj_t* obj, int fd); - /** * Check of the name matches the object file's object name. * @@ -371,8 +395,8 @@ void rtems_rtl_obj_erase_sections (rtems_rtl_obj_t* obj); * @retval NULL The section was not found. * @return rtems_rtl_obj_sect_t* The named section. */ -rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, - const char* name); +rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (const rtems_rtl_obj_t* obj, + const char* name); /** * Find a section given a section's index number. @@ -382,21 +406,21 @@ rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section (rtems_rtl_obj_t* obj, * @retval NULL The section was not found. * @return rtems_rtl_obj_sect_t* The found section. */ -rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section_by_index (rtems_rtl_obj_t* obj, - int index); +rtems_rtl_obj_sect_t* rtems_rtl_obj_find_section_by_index (const rtems_rtl_obj_t* obj, + int index); /** - * The text size of the object file. Only use once all the sections has been - * added. It includes alignments between sections that are part of the object's - * text area. The consts sections are included in this section. + * The text section size. Only use once all the sections has been added. It + * includes alignments between sections that are part of the object's text + * area. The consts sections are included in this section. * * @param obj The object file's descriptor. * @return size_t The size of the text area of the object file. */ -size_t rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj); +size_t rtems_rtl_obj_text_size (const rtems_rtl_obj_t* obj); /** - * The text section alignment of the object file. Only use once all the + * The text section alignment for the object file. Only use once all the * sections has been added. The section alignment is the alignment of the first * text type section loaded the text section. * @@ -406,20 +430,20 @@ size_t rtems_rtl_obj_text_size (rtems_rtl_obj_t* obj); * @param obj The object file's descriptor. * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. */ -uint32_t rtems_rtl_obj_text_alignment (rtems_rtl_obj_t* obj); +uint32_t rtems_rtl_obj_text_alignment (const rtems_rtl_obj_t* obj); /** - * The const size of the object file. Only use once all the sections has been - * added. It includes alignments between sections that are part of the object's - * const area. The consts sections are included in this section. + * The const section size. Only use once all the sections has been added. It + * includes alignments between sections that are part of the object's const + * area. The consts sections are included in this section. * * @param obj The object file's descriptor. * @return size_t The size of the const area of the object file. */ -size_t rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj); +size_t rtems_rtl_obj_const_size (const rtems_rtl_obj_t* obj); /** - * The const section alignment of the object file. Only use once all the + * The const section alignment for the object file. Only use once all the * sections has been added. The section alignment is the alignment of the first * const type section loaded the const section. * @@ -429,20 +453,42 @@ size_t rtems_rtl_obj_const_size (rtems_rtl_obj_t* obj); * @param obj The object file's descriptor. * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. */ -uint32_t rtems_rtl_obj_const_alignment (rtems_rtl_obj_t* obj); +uint32_t rtems_rtl_obj_const_alignment (const rtems_rtl_obj_t* obj); + +/** + * The eh section size. Only use once all the sections has been added. It + * includes alignments between sections that are part of the object's bss area. + * + * @param obj The object file's descriptor. + * @return size_t The size of the bss area of the object file. + */ +size_t rtems_rtl_obj_eh_size (const rtems_rtl_obj_t* obj); + +/** + * The eh section alignment for the object file. Only use once all the sections + * has been added. The section alignment is the alignment of the first bss type + * section loaded the bss section. + * + * You can assume the alignment is a positive integral power of 2 if not 0 or + * 1. If 0 or 1 then there is no alignment. + * + * @param obj The object file's descriptor. + * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. + */ +uint32_t rtems_rtl_obj_eh_alignment (const rtems_rtl_obj_t* obj); /** - * The data size of the object file. Only use once all the sections has been - * added. It includes alignments between sections that are part of the object's - * data area. + * The data section size. Only use once all the sections has been added. It + * includes alignments between sections that are part of the object's data + * area. * * @param obj The object file's descriptor. * @return size_t The size of the data area of the object file. */ -size_t rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj); +size_t rtems_rtl_obj_data_size (const rtems_rtl_obj_t* obj); /** - * The data section alignment of the object file. Only use once all the + * The data section alignment for the object file. Only use once all the * sections has been added. The section alignment is the alignment of the first * data type section loaded the data section. * @@ -452,20 +498,19 @@ size_t rtems_rtl_obj_data_size (rtems_rtl_obj_t* obj); * @param obj The object file's descriptor. * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. */ -uint32_t rtems_rtl_obj_data_alignment (rtems_rtl_obj_t* obj); +uint32_t rtems_rtl_obj_data_alignment (const rtems_rtl_obj_t* obj); /** - * The bss size of the object file. Only use once all the sections has been - * added. It includes alignments between sections that are part of the object's - * bss area. + * The bss section size. Only use once all the sections has been added. It + * includes alignments between sections that are part of the object's bss area. * * @param obj The object file's descriptor. * @return size_t The size of the bss area of the object file. */ -size_t rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj); +size_t rtems_rtl_obj_bss_size (const rtems_rtl_obj_t* obj); /** - * The bss section alignment of the object file. Only use once all the + * The bss section alignment for the object file. Only use once all the * sections has been added. The section alignment is the alignment of the first * bss type section loaded the bss section. * @@ -475,7 +520,7 @@ size_t rtems_rtl_obj_bss_size (rtems_rtl_obj_t* obj); * @param obj The object file's descriptor. * @return uint32_t The alignment. Can be 0 or 1 for not aligned or the alignment. */ -uint32_t rtems_rtl_obj_bss_alignment (rtems_rtl_obj_t* obj); +uint32_t rtems_rtl_obj_bss_alignment (const rtems_rtl_obj_t* obj); /** * Relocate the object file. The object file's section are parsed for any diff --git a/cpukit/libdl/rtl-rap.c b/cpukit/libdl/rtl-rap.c index a7fcb9f953..cb7b751cd0 100644 --- a/cpukit/libdl/rtl-rap.c +++ b/cpukit/libdl/rtl-rap.c @@ -427,20 +427,22 @@ rtems_rtl_rap_relocate (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) } /** - * The structure of obj->detail is + * The structure of obj->linkmap is: * * |object_detail(0..obj_num)|section_detail(0..sec_num[0..obj_num])| * obj_name(0..obj_num)|section_name(0..sec_num[0..obj_num]) * */ static bool -rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) +rtems_rtl_rap_load_linkmap (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) { + void* detail; struct link_map* tmp1; - section_detail* tmp2; - uint32_t obj_detail_size; - uint32_t pos = 0; - int i,j; + section_detail* tmp2; + uint32_t obj_detail_size; + uint32_t pos = 0; + int i; + int j; obj_detail_size = sizeof (struct link_map) * obj->obj_num; @@ -449,26 +451,31 @@ rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) obj_detail_size += (obj->sec_num[i] * sizeof (section_detail)); } - obj->detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, - obj_detail_size + rap->strtable_size, true); + detail = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, + obj_detail_size + rap->strtable_size, true); - if (!obj->detail) + if (!detail) { rap->strtable_size = 0; rtems_rtl_set_error (ENOMEM, "no memory for obj global syms"); return false; } - rap->strtable = obj->detail + obj_detail_size; + rap->strtable = detail + obj_detail_size; - /* Read the obj names and section names */ - if (!rtems_rtl_obj_comp_read (rap->decomp, rap->strtable, + /* + * Read the obj names and section names + */ + if (!rtems_rtl_obj_comp_read (rap->decomp, + rap->strtable, rap->strtable_size)) { - rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->detail); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, detail); return false; } + obj->linkmap = (struct link_map*) detail; + if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { if (rap->rpathlen > 0) @@ -489,7 +496,7 @@ rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) for (i = 0; i < obj->obj_num; ++i) { - tmp1 = (struct link_map*) (obj->detail) + i; + tmp1 = obj->linkmap + i; tmp1->name = rap->strtable + pos; tmp1->sec_num = obj->sec_num[i]; tmp1->rpathlen = rap->rpathlen; @@ -509,17 +516,17 @@ rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) } } - tmp2 =(section_detail*) ((struct link_map*) (obj->detail) + obj->obj_num); + tmp2 = (section_detail*) (obj->linkmap + obj->obj_num); for (i = 0; i < obj->obj_num; ++i) { if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) { - printf ("File %d: %s\n", i, ((struct link_map*) obj->detail + i)->name); - printf ("Section: %d sections\n",(unsigned int) obj->sec_num[i]); + printf ("File %d: %s\n", i, (obj->linkmap + i)->name); + printf ("Section: %d sections\n", (unsigned int) obj->sec_num[i]); } - ((struct link_map*)obj->detail + i)->sec_detail = tmp2; + obj->linkmap[i].sec_detail = tmp2; for (j = 0; j < obj->sec_num[i]; ++j) { @@ -532,7 +539,8 @@ rtems_rtl_rap_load_details (rtems_rtl_rap_t* rap, rtems_rtl_obj_t* obj) !rtems_rtl_rap_read_uint32 (rap->decomp, &offset) || !rtems_rtl_rap_read_uint32 (rap->decomp, &size)) { - rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->detail); + rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->linkmap); + obj->linkmap = NULL; return false; } @@ -907,7 +915,7 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd) if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL)) printf ("rtl: rap: details: obj_num=%lu\n", obj->obj_num); - if (!rtems_rtl_rap_load_details (&rap, obj)) + if (!rtems_rtl_rap_load_linkmap (&rap, obj)) return false; } @@ -975,6 +983,13 @@ rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd) return true; } +bool +rtems_rtl_rap_file_unload (rtems_rtl_obj_t* obj) +{ + (void) obj; + return true; +} + rtems_rtl_loader_format_t* rtems_rtl_rap_file_sig (void) { diff --git a/cpukit/libdl/rtl-rap.h b/cpukit/libdl/rtl-rap.h index f828b1fbdc..eca6e9ea4a 100644 --- a/cpukit/libdl/rtl-rap.h +++ b/cpukit/libdl/rtl-rap.h @@ -40,6 +40,13 @@ bool rtems_rtl_rap_file_check (rtems_rtl_obj_t* obj, int fd); */ bool rtems_rtl_rap_file_load (rtems_rtl_obj_t* obj, int fd); +/** + * The RAP format unload handler. + * + * @param obj The object to unload. + */ +bool rtems_rtl_rap_file_unload (rtems_rtl_obj_t* obj); + /** * The RAP format signature handler. * diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c index 20a6aabe05..a10c931c6e 100644 --- a/cpukit/libdl/rtl-shell.c +++ b/cpukit/libdl/rtl-shell.c @@ -25,7 +25,7 @@ * Flag the targets where off_t is 32 bits. This is not a compiler type * so we can't rely on prerdefines. */ -#if defined(__m32r__) || defined(__moxie__) +#if defined(__moxie__) #define PRIdoff_t PRIo32 #else #define PRIdoff_t PRIo64 diff --git a/cpukit/libdl/rtl-unwind-dw2.c b/cpukit/libdl/rtl-unwind-dw2.c new file mode 100644 index 0000000000..d9237c5b7e --- /dev/null +++ b/cpukit/libdl/rtl-unwind-dw2.c @@ -0,0 +1,71 @@ +/* + * COPYRIGHT (c) 2012-2016 Chris Johns + * + * 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_rtld + * + * @brief RTEMS Run-Time Link Editor + * + * This is the RTL implementation. + */ + +#if HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include "rtl-elf.h" +#include "rtl-error.h" +#include "rtl-unwind.h" +#include "rtl-unwind-dw2.h" + +/* + * These interfaces are not exported outside the GCC source. + */ +void __register_frame (void *begin); +void __deregister_frame (void *begin); + +bool +rtems_rtl_elf_unwind_dw2_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags) +{ + return + ((flags & RTEMS_RTL_OBJ_SECT_CONST) != 0) && + ((strcmp(name, ".eh_frame") == 0) || + (strncmp(name, ".gcc_except_table.", sizeof (".gcc_except_table.") - 1) == 0)); +} + +bool +rtems_rtl_elf_unwind_dw2_register (const rtems_rtl_obj_t* obj) +{ + rtems_rtl_obj_sect_t* sect = rtems_rtl_obj_find_section (obj, ".eh_frame"); + + if (sect != NULL && sect->size > 0 && sect->base != NULL) + { + __register_frame (sect->base); + } + + return true; +} + +bool rtems_rtl_elf_unwind_dw2_deregister (const rtems_rtl_obj_t* obj) +{ + rtems_rtl_obj_sect_t* sect = rtems_rtl_obj_find_section (obj, ".eh_frame"); + + if (sect != NULL && sect->size > 0 && sect->base != NULL) + { + __deregister_frame (sect->base); + } + + return true; +} diff --git a/cpukit/libdl/rtl-unwind-dw2.h b/cpukit/libdl/rtl-unwind-dw2.h new file mode 100644 index 0000000000..55b97970c2 --- /dev/null +++ b/cpukit/libdl/rtl-unwind-dw2.h @@ -0,0 +1,83 @@ +/* + * COPYRIGHT (c) 2016 Chris Johns + * + * 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 Unwind DWARF Support. + */ + +#if !defined (_RTEMS_RTL_UNWIND_DW2_H_) +#define _RTEMS_RTL_UNWIND_DW2_H_ + +#include "rtl-elf.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if __SIZEOF_LONG__ >= __SIZEOF_POINTER__ + typedef long rtems_rtl_elf_unwind_dw2_sleb128; + typedef unsigned long rtems_rtl_elf_unwind_dw2_uleb128; +#elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__ + typedef long long rtems_rtl_elf_unwind_dw2_sleb128; + typedef unsigned long long rtems_rtl_elf_unwind_dw2_uleb128; +#else + #error No DW2 type available. +#endif + +/** + * Architecture specific handler to check if a section contains exception + * handler data.. + * + * @param obj The object file. + * @param name The section's name. + * @param uint32 flags The object file's flags. + * @retval true The section contains unwind information. + * @retval false The section does not contain unwind information. + */ +bool rtems_rtl_elf_unwind_dw2_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags); + +/** + * Architecture specific handler to add an object file's unwind information to + * the base image. + * + * @param obj The object file. + * @retval true The unwind information has been registered. + * @retval false The unwind information could not be registered. + */ +bool rtems_rtl_elf_unwind_dw2_register (const rtems_rtl_obj_t* obj); + +/** + * Architecture specific handler to remove an object file's unwind information + * from the base image. + * + * @param obj The object file. + * @retval true The unwind information has been deregistered. + * @retval false The unwind information could not be deregistered. + */ +bool rtems_rtl_elf_unwind_dw2_deregister (const rtems_rtl_obj_t* obj); + +/** + * Read signed and unsigned LEB128 values. + */ +const uint8_t* rtems_rtl_elf_unwind_dw2_read_uleb128 (const uint8_t* data, + rtems_rtl_elf_unwind_dw2_uleb128* val); +const uint8_t* rtems_rtl_elf_unwind_dw2_read_sleb128 (const uint8_t* data, + rtems_rtl_elf_unwind_dw2_sleb128* val); + +bool rtems_rtl_elf_unwind_dw2_relocate (const Elf_Addr* where, Elf_Word value, Elf_Word mask); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/cpukit/libdl/rtl-unwind.h b/cpukit/libdl/rtl-unwind.h new file mode 100644 index 0000000000..f88787e1ba --- /dev/null +++ b/cpukit/libdl/rtl-unwind.h @@ -0,0 +1,63 @@ +/* + * COPYRIGHT (c) 2016 Chris Johns + * + * 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 Unwind Support. + */ + +#if !defined (_RTEMS_RTL_UNWIND_H_) +#define _RTEMS_RTL_UNWIND_H_ + +#include "rtl-elf.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * Architecture specific handler to check if a section contains exception + * handler data.. + * + * @param obj The object file. + * @param name The section's name. + * @param uint32 flags The object file's flags. + * @retval true The section contains unwind information. + * @retval false The section does not contain unwind information. + */ +bool rtems_rtl_elf_unwind_parse (const rtems_rtl_obj_t* obj, + const char* name, + uint32_t flags); + +/** + * Architecture specific handler to add an object file's unwind information to + * the base image. + * + * @param obj The object file. + * @retval true The unwind information has been registered. + * @retval false The unwind information could not be registered. + */ +bool rtems_rtl_elf_unwind_register (rtems_rtl_obj_t* obj); + +/** + * Architecture specific handler to remove an object file's unwind information + * from the base image. + * + * @param obj The object file. + * @retval true The unwind information has been deregistered. + * @retval false The unwind information could not be deregistered. + */ +bool rtems_rtl_elf_unwind_deregister (rtems_rtl_obj_t* obj); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c index abfcf25f1c..505225116e 100644 --- a/cpukit/libdl/rtl.c +++ b/cpukit/libdl/rtl.c @@ -62,6 +62,7 @@ * Static RTL data is returned to the user when the linker is locked. */ static rtems_rtl_data_t* rtl; +static bool rtl_data_init; /** * Define a default base global symbol loader function that is weak @@ -94,12 +95,26 @@ rtems_rtl_data_init (void) rtems_status_code sc; rtems_id lock; + /* + * We cannot set an error in this code because there is no RTL data to + * hold it. + */ + + if (rtl_data_init) + { + rtems_libio_unlock (); + return false; + } + + rtl_data_init = true; + /* * Always in the heap. */ rtl = malloc (sizeof (rtems_rtl_data_t)); if (!rtl) { + rtems_libio_unlock (); errno = ENOMEM; return false; } @@ -120,6 +135,7 @@ rtems_rtl_data_init (void) if (sc != RTEMS_SUCCESSFUL) { free (rtl); + rtems_libio_unlock (); return false; } @@ -128,6 +144,7 @@ rtems_rtl_data_init (void) { rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -143,6 +160,7 @@ rtems_rtl_data_init (void) { rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -152,6 +170,7 @@ rtems_rtl_data_init (void) rtems_rtl_symbol_table_close (&rtl->globals); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -162,6 +181,7 @@ rtems_rtl_data_init (void) rtems_rtl_unresolved_table_close (&rtl->unresolved); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -173,6 +193,7 @@ rtems_rtl_data_init (void) rtems_rtl_symbol_table_close (&rtl->globals); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -185,6 +206,7 @@ rtems_rtl_data_init (void) rtems_rtl_symbol_table_close (&rtl->globals); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -198,6 +220,7 @@ rtems_rtl_data_init (void) rtems_rtl_symbol_table_close (&rtl->globals); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -212,6 +235,7 @@ rtems_rtl_data_init (void) rtems_rtl_symbol_table_close (&rtl->globals); rtems_semaphore_delete (lock); free (rtl); + rtems_libio_unlock (); return false; } @@ -288,7 +312,7 @@ rtems_rtl_obj_caches (rtems_rtl_obj_cache_t** symbols, } void -rtems_rtl_obj_caches_flush () +rtems_rtl_obj_caches_flush (void) { if (rtl) { @@ -438,6 +462,7 @@ rtems_rtl_load_object (const char* name, int mode) if (!rtems_rtl_obj_find_file (obj, name)) { rtems_rtl_obj_free (obj); + rtems_rtl_obj_caches_flush (); return NULL; } @@ -446,9 +471,12 @@ rtems_rtl_load_object (const char* name, int mode) if (!rtems_rtl_obj_load (obj)) { rtems_rtl_obj_free (obj); + rtems_rtl_obj_caches_flush (); return NULL; } + rtems_rtl_obj_caches_flush (); + rtems_rtl_unresolved_resolve (); } @@ -514,6 +542,9 @@ rtems_rtl_unload_object (rtems_rtl_obj_t* obj) obj->flags &= ~RTEMS_RTL_OBJ_LOCKED; ok = rtems_rtl_obj_unload (obj); + + rtems_rtl_obj_free (obj); + rtems_rtl_obj_caches_flush (); } return ok; diff --git a/cpukit/libdl/rtl.h b/cpukit/libdl/rtl.h index 234fc32428..fe9a7df081 100644 --- a/cpukit/libdl/rtl.h +++ b/cpukit/libdl/rtl.h @@ -112,7 +112,7 @@ struct rtems_rtl_data_s }; /** - * Get the RTL data with out locking. This call assmes the RTL is locked. + * Get the RTL data with out locking. This call assumes the RTL is locked. * * @return rtems_rtl_data_t* The RTL data after being locked. * @retval NULL The RTL data is not initialised. diff --git a/cpukit/preinstall.am b/cpukit/preinstall.am index 0758ec5263..a99330d5ba 100644 --- a/cpukit/preinstall.am +++ b/cpukit/preinstall.am @@ -212,6 +212,10 @@ $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h: libdl/rtl-sym.h $(PROJECT_INCLUDE)/rtems $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-sym.h +$(PROJECT_INCLUDE)/rtems/rtl/rtl-trace.h: libdl/rtl-trace.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp) + $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rtl-trace.h +PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rtl-trace.h + $(PROJECT_INCLUDE)/rtems/rtl/rap.h: libdl/rap.h $(PROJECT_INCLUDE)/rtems/rtl/$(dirstamp) $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rtl/rap.h PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rtl/rap.h -- cgit v1.2.3