diff options
Diffstat (limited to 'cpukit')
-rw-r--r-- | cpukit/libdl/include/sys/exec_elf.h | 10 | ||||
-rw-r--r-- | cpukit/libdl/rtl-elf.c | 14 | ||||
-rw-r--r-- | cpukit/libdl/rtl-mdreloc-sparc.c | 3 | ||||
-rw-r--r-- | cpukit/libdl/rtl-obj.c | 159 | ||||
-rw-r--r-- | cpukit/libdl/rtl-obj.h | 16 |
5 files changed, 166 insertions, 36 deletions
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/rtl-elf.c b/cpukit/libdl/rtl-elf.c index 37775ff776..be2f06a7ba 100644 --- a/cpukit/libdl/rtl-elf.c +++ b/cpukit/libdl/rtl-elf.c @@ -656,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: @@ -712,7 +717,7 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj_t* obj, int fd, Elf_Ehdr* ehdr) default: /* - * See there are architecture specific flags? + * See if there are architecture specific flags? */ flags = rtems_rtl_elf_section_flags (obj, &shdr); if (flags == 0) @@ -729,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, diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c index 38b385070e..8d1239421d 100644 --- a/cpukit/libdl/rtl-mdreloc-sparc.c +++ b/cpukit/libdl/rtl-mdreloc-sparc.c @@ -253,7 +253,8 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj_t* obj, if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) printf ("rtl: %s %p @ %p in %s\n", - reloc_names[type], (void *)tmp, where, rtems_rtl_obj_oname (obj)); + reloc_names[ELF_R_TYPE(rela->r_info)], + (void *)tmp, where, rtems_rtl_obj_oname (obj)); return true; } diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c index b27f28b9a9..bb0bc8d543 100644 --- a/cpukit/libdl/rtl-obj.c +++ b/cpukit/libdl/rtl-obj.c @@ -601,12 +601,12 @@ 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) @@ -632,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; @@ -643,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; @@ -667,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, @@ -679,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 (l:%zi m:%04lx)\n", - sect->name, sect->base, sect->size, sect->flags); + 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); @@ -763,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)) { @@ -780,6 +873,14 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj_t* 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. */ diff --git a/cpukit/libdl/rtl-obj.h b/cpukit/libdl/rtl-obj.h index 9ec184be1a..6a35a72822 100644 --- a/cpukit/libdl/rtl-obj.h +++ b/cpukit/libdl/rtl-obj.h @@ -102,8 +102,19 @@ typedef struct rtems_rtl_loader_table_s #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_CTOR (1 << 14) /**< Section contains constructors. */ -#define RTEMS_RTL_OBJ_SECT_DTOR (1 << 15) /**< Section contains destructors. */ +#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 @@ -124,6 +135,7 @@ struct rtems_rtl_obj_sect_s uint32_t flags; /**< The section's flags. */ void* base; /**< The base address of the section in * memory. */ + int load_order; /**< Order we load sections. */ }; /** |