summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/libdl/include/sys/exec_elf.h10
-rw-r--r--cpukit/libdl/rtl-elf.c14
-rw-r--r--cpukit/libdl/rtl-mdreloc-sparc.c3
-rw-r--r--cpukit/libdl/rtl-obj.c159
-rw-r--r--cpukit/libdl/rtl-obj.h16
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. */
};
/**