summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/Makefile.am2
-rw-r--r--cpukit/libdl/Makefile.am1
-rw-r--r--cpukit/libdl/dlfcn.c2
-rw-r--r--cpukit/libdl/include/arch/arm/machine/elf_machdep.h3
-rw-r--r--cpukit/libdl/include/sys/exec_elf.h10
-rw-r--r--cpukit/libdl/rap.c1
-rw-r--r--cpukit/libdl/rtl-allocator.c26
-rw-r--r--cpukit/libdl/rtl-allocator.h7
-rw-r--r--cpukit/libdl/rtl-debugger.c14
-rw-r--r--cpukit/libdl/rtl-elf.c106
-rw-r--r--cpukit/libdl/rtl-elf.h26
-rw-r--r--cpukit/libdl/rtl-error.c17
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c124
-rw-r--r--cpukit/libdl/rtl-mdreloc-bfin.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-h8300.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-i386.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-lm32.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-m68k.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-mips.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-moxie.c29
-rw-r--r--cpukit/libdl/rtl-mdreloc-powerpc.c44
-rw-r--r--cpukit/libdl/rtl-mdreloc-sparc.c49
-rw-r--r--cpukit/libdl/rtl-mdreloc-v850.c29
-rw-r--r--cpukit/libdl/rtl-obj.c333
-rw-r--r--cpukit/libdl/rtl-obj.h181
-rw-r--r--cpukit/libdl/rtl-rap.c55
-rw-r--r--cpukit/libdl/rtl-rap.h7
-rw-r--r--cpukit/libdl/rtl-shell.c2
-rw-r--r--cpukit/libdl/rtl-unwind-dw2.c71
-rw-r--r--cpukit/libdl/rtl-unwind-dw2.h83
-rw-r--r--cpukit/libdl/rtl-unwind.h63
-rw-r--r--cpukit/libdl/rtl.c33
-rw-r--r--cpukit/libdl/rtl.h2
-rw-r--r--cpukit/preinstall.am4
34 files changed, 1239 insertions, 259 deletions
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 <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
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
@@ -55,6 +55,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.
*
@@ -137,13 +149,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.
*
* @param obj The object to load.
@@ -152,6 +157,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.
*
* @return rtems_rtl_loader_format_t* The format's signature.
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 <errno.h>
#include <stdio.h>
#include <stdarg.h>
@@ -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 <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <unwind.h>
+#include <unwind-arm-common.h>
#include <rtems/rtl/rtl.h>
#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<cond> */
@@ -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<size; i++)
+ for (i = size - 1; i >= 0; i--)
tmp = (tmp << 8) | ptr[i];
tmp &= ~mask;
tmp |= value;
/* Write it back out. */
- for (i=0; i<size; i++)
- ptr[i] = ((tmp >> (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, &sect->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, &sect->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,6 +864,8 @@ 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",
@@ -735,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.
*/
@@ -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. */
};
/**
@@ -258,6 +280,20 @@ static inline bool rtems_rtl_obj_aname_valid (const rtems_rtl_obj_t* obj)
}
/**
+ * 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.
*
* @retval NULL No memory for the object.
@@ -300,18 +336,6 @@ bool rtems_rtl_parse_name (const char* name,
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.
*
* @param obj The object file's descriptor.
@@ -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
@@ -41,6 +41,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.
*
* @return rtems_rtl_loader_format_t* The format's signature.
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 <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtld
+ *
+ * @brief RTEMS Run-Time Link Editor
+ *
+ * This is the RTL implementation.
+ */
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+#include <stdio.h>
+
+#include <rtems/rtl/rtl.h>
+#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 <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker 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 <chrisj@rtems.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker 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
@@ -95,11 +96,25 @@ rtems_rtl_data_init (void)
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