summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-01-09 22:14:11 +1100
committerChris Johns <chrisj@rtems.org>2019-01-09 22:33:23 +1100
commita87356db51791224ca525d248804a81d2e89d7c9 (patch)
treec17638a3314af9712f6f3fa9c898be6af5cde631
parentb1212a5cfe48dbf5ec30120d21a724cfe0647e90 (diff)
libdl: Fix the support for constructors and desctructors.rtl-ctor-dtor
- Fix the handling of pending objects. - Add a constructor flags in objects to track then being called.
-rw-r--r--cpukit/include/rtems/rtl/rtl-obj.h1
-rw-r--r--cpukit/libdl/rtl-elf.c21
-rw-r--r--cpukit/libdl/rtl-mdreloc-arm.c12
-rw-r--r--cpukit/libdl/rtl-unresolved.c4
-rw-r--r--cpukit/libdl/rtl.c93
-rw-r--r--cpukit/score/cpu/arm/include/machine/elf_machdep.h72
6 files changed, 144 insertions, 59 deletions
diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index bc503887e2..b7522a7d39 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -168,6 +168,7 @@ typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj,
#define RTEMS_RTL_OBJ_RELOC_TAG (1 << 3) /**< Tag the object as visited when reloc
* parsing. */
#define RTEMS_RTL_OBJ_DEP_VISITED (1 << 4) /**< Dependency loop detection. */
+#define RTEMS_RTL_OBJ_CTOR_RUN (1 << 5) /**< Constructors have been called. */
/**
* RTL Object. There is one for each object module loaded plus one for the base
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index caa37e6bab..63242acaae 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -993,6 +993,24 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
flags = RTEMS_RTL_OBJ_SECT_STR;
break;
+ case SHT_INIT_ARRAY:
+ /*
+ * Constructors are text and need to be loaded.
+ */
+ flags = (RTEMS_RTL_OBJ_SECT_CTOR |
+ RTEMS_RTL_OBJ_SECT_TEXT |
+ RTEMS_RTL_OBJ_SECT_LOAD);
+ break;
+
+ case SHT_FINI_ARRAY:
+ /*
+ * Destructors are text and need to be loaded.
+ */
+ flags = (RTEMS_RTL_OBJ_SECT_DTOR |
+ RTEMS_RTL_OBJ_SECT_TEXT |
+ RTEMS_RTL_OBJ_SECT_LOAD);
+ break;
+
default:
/*
* See if there are architecture specific flags?
@@ -1019,6 +1037,9 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
if ((shdr.sh_flags & SHF_LINK_ORDER) != 0)
flags |= RTEMS_RTL_OBJ_SECT_LINK;
+ /*
+ * Some architexctures support a named PROGBIT section for INIT/FINI.
+ */
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-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index 96e14fc676..ad489d6d87 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -7,6 +7,7 @@
#include <sys/cdefs.h>
#include <errno.h>
+#include <inttypes.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
@@ -193,6 +194,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
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(TARGET1): /* Equivalent to REL32 */
case R_TYPE(TARGET2): /* Equivalent to REL32 */
if (__predict_true(RELOC_ALIGNED_P(where))) {
tmp = *where + symvalue;
@@ -249,8 +251,8 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
break;
case R_TYPE(THM_JUMP24):
- /* same to THM_CALL; insn b.w */
- case R_TYPE(THM_CALL):
+ /* same as THM_PC22; insn b.w */
+ case R_TYPE(THM_PC22):
upper_insn = *(uint16_t *)where;
lower_insn = *((uint16_t *)where + 1);
sign = (upper_insn & (1 << 10)) >> 10;
@@ -322,7 +324,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
tmp = tmp - (Elf_Addr)where;
if (((Elf_Sword)tmp > 0x7ffffe) || ((Elf_Sword)tmp < -0x800000)) {
- rtems_rtl_set_error (EINVAL, "%s: Overflow %ld "
+ rtems_rtl_set_error (EINVAL, "%s: Overflow %" PRIu32 " "
"THM_JUMP19 relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return false;
@@ -342,12 +344,12 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj* obj,
break;
default:
- printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+ printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p, "
"contents = %p\n",
ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
(void *)rel->r_offset, (void *)*where);
rtems_rtl_set_error (EINVAL,
- "%s: Unsupported relocation type %ld "
+ "%s: Unsupported relocation type %" PRIu32 " "
"in non-PLT relocations",
sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
return false;
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index 4e81c3c64e..7e2d920594 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -181,7 +181,8 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
if (rec->rec.reloc.name == rd->name && rec->rec.reloc.obj != NULL)
{
if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
- printf ("rtl: unresolv: resolve reloc: %s\n", rd->name_rec->rec.name.name);
+ printf ("rtl: unresolv: resolve reloc: %s\n",
+ rd->name_rec->rec.name.name);
rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);
@@ -193,6 +194,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
if (rec->rec.reloc.obj->unresolved == 0)
{
pending = rtems_rtl_pending_unprotected ();
+ rtems_chain_extract (&rec->rec.reloc.obj->link);
rtems_chain_append (pending, &rec->rec.reloc.obj->link);
}
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
index f331cbbf02..a3664c7e34 100644
--- a/cpukit/libdl/rtl.c
+++ b/cpukit/libdl/rtl.c
@@ -512,6 +512,8 @@ rtems_rtl_load_object (const char* name, int mode)
return NULL;
}
+ rtems_chain_append (&rtl->pending, &obj->link);
+
/*
* Find the file in the file system using the search path. The fname field
* will point to a valid file name if found.
@@ -523,8 +525,6 @@ rtems_rtl_load_object (const char* name, int mode)
return NULL;
}
- rtems_chain_append (&rtl->pending, &obj->link);
-
if (!rtems_rtl_obj_load (obj))
{
rtems_chain_extract (&obj->link);
@@ -533,6 +533,16 @@ rtems_rtl_load_object (const char* name, int mode)
return NULL;
}
+ /*
+ * If there are unresolved externals remove from the pending queue and place
+ * on the objects list until the symbols are resolved.
+ */
+ if (obj->unresolved != 0)
+ {
+ rtems_chain_extract (&obj->link);
+ rtems_chain_append (&rtl->objects, &obj->link);
+ }
+
rtems_rtl_obj_caches_flush ();
}
@@ -572,34 +582,34 @@ rtems_rtl_load (const char* name, int mode)
node = rtems_chain_first (&rtl->pending);
while (!rtems_chain_is_tail (&rtl->pending, node))
{
- rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+ rtems_rtl_obj* pobj = (rtems_rtl_obj*) node;
/*
* Move to the next pending object file and place this object file on the
* RTL's objects list.
*/
- node = rtems_chain_next (&obj->link);
- rtems_chain_extract (&obj->link);
- rtems_chain_append (&rtl->objects, &obj->link);
+ node = rtems_chain_next (&pobj->link);
+ rtems_chain_extract (&pobj->link);
+ rtems_chain_append (&rtl->objects, &pobj->link);
/*
* Make sure the object file and cache is synchronized.
*/
- rtems_rtl_obj_synchronize_cache (obj);
+ rtems_rtl_obj_synchronize_cache (pobj);
/*
- * Run any local constructors if this is the first user because the
- * object file will have just been loaded. Unlock the linker to avoid any
- * dead locks if the object file needs to load files or update the symbol
- * table. We also do not want a constructor to unload this object file.
+ * Run any local constructors if they have not been run. Unlock the linker
+ * to avoid any dead locks if the object file needs to load files or
+ * update the symbol table. We also do not want a constructor to unload
+ * this object file.
*/
- if (obj->users == 1)
+ if ((pobj->flags & RTEMS_RTL_OBJ_CTOR_RUN) == 0)
{
- obj->flags |= RTEMS_RTL_OBJ_LOCKED;
+ pobj->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_CTOR_RUN;
rtems_rtl_unlock ();
- rtems_rtl_obj_run_ctors (obj);
+ rtems_rtl_obj_run_ctors (pobj);
rtems_rtl_lock ();
- obj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
+ pobj->flags &= ~RTEMS_RTL_OBJ_LOCKED;
}
}
}
@@ -623,7 +633,7 @@ rtems_rtl_unload_object (rtems_rtl_obj* obj)
}
/*
- * Move the object file from the objects list to the pending list if unloaded.
+ * The object file cannot be unloaded if it is referenced.
*/
if (rtems_rtl_obj_get_reference (obj) > 0)
{
@@ -649,30 +659,43 @@ rtems_rtl_unload (rtems_rtl_obj* obj)
{
rtems_chain_control unloading;
rtems_chain_node* node;
+ bool orphaned_found = true;
+ int loop = 0;
/*
- * Remove the orphaned object files from the objects list. This makes the
- * list private and any changes in any desctructors will effect the run.
+ * Remove the orphaned object files from the objects list. The unloading is
+ * private so any changes in any desctructors will not effect the list as it
+ * is being iterated over.
+ *
+ * To avoid maintaining a complex tree loop while oprhans are still be found.
*/
+
rtems_chain_initialize_empty (&unloading);
- node = rtems_chain_first (&rtl->objects);
- while (!rtems_chain_is_tail (&rtl->objects, node))
+ while (orphaned_found)
{
- rtems_chain_node* next_node = rtems_chain_next (node);
- rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
- if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
- printf ("rtl: unload object: %s: %s\n",
- rtems_rtl_obj_oname (obj),
- rtems_rtl_obj_orphaned (uobj) ? "orphaned" : "inuse");
- if (rtems_rtl_obj_orphaned (uobj))
+ orphaned_found = false;
+ ++loop;
+ node = rtems_chain_first (&rtl->objects);
+ while (!rtems_chain_is_tail (&rtl->objects, node))
{
- rtems_rtl_obj_remove_dependencies (uobj);
- rtems_chain_extract (&uobj->link);
- rtems_chain_append (&unloading, &uobj->link);
- uobj->flags |= RTEMS_RTL_OBJ_LOCKED;
+ rtems_chain_node* next_node = rtems_chain_next (node);
+ rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
+ if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNLOAD))
+ printf ("rtl: unload object: %3i: %9s: %s\n",
+ loop,
+ rtems_rtl_obj_orphaned (uobj) ? "orphaned" : "inuse",
+ rtems_rtl_obj_oname (uobj));
+ if (rtems_rtl_obj_orphaned (uobj))
+ {
+ orphaned_found = true;
+ rtems_rtl_obj_remove_dependencies (uobj);
+ rtems_chain_extract (&uobj->link);
+ rtems_chain_append (&unloading, &uobj->link);
+ uobj->flags |= RTEMS_RTL_OBJ_LOCKED;
+ }
+ node = next_node;
}
- node = next_node;
}
/*
@@ -684,7 +707,11 @@ rtems_rtl_unload (rtems_rtl_obj* obj)
while (!rtems_chain_is_tail (&unloading, node))
{
rtems_rtl_obj* uobj = (rtems_rtl_obj*) node;
- rtems_rtl_obj_run_dtors (uobj);
+ if ((uobj->flags & RTEMS_RTL_OBJ_CTOR_RUN) != 0)
+ {
+ rtems_rtl_obj_run_dtors (uobj);
+ uobj->flags &= ~RTEMS_RTL_OBJ_CTOR_RUN;
+ }
node = rtems_chain_next (node);
}
diff --git a/cpukit/score/cpu/arm/include/machine/elf_machdep.h b/cpukit/score/cpu/arm/include/machine/elf_machdep.h
index 8f01d05212..6196879481 100644
--- a/cpukit/score/cpu/arm/include/machine/elf_machdep.h
+++ b/cpukit/score/cpu/arm/include/machine/elf_machdep.h
@@ -1,4 +1,7 @@
-/* $NetBSD: elf_machdep.h,v 1.8 2009/05/30 05:56:52 skrll Exp $ */
+/* $NetBSD: elf_machdep.h,v 1.19 2017/11/06 03:47:45 christos Exp $ */
+
+#ifndef _ARM_ELF_MACHDEP_H_
+#define _ARM_ELF_MACHDEP_H_
#if defined(__ARMEB__)
#define ELF32_MACHDEP_ENDIANNESS ELFDATA2MSB
@@ -24,7 +27,13 @@
#define EF_ARM_NEW_ABI 0x00000080
#define EF_ARM_OLD_ABI 0x00000100
#define EF_ARM_SOFT_FLOAT 0x00000200
+#define EF_ARM_BE8 0x00800000
#define EF_ARM_EABIMASK 0xff000000
+#define EF_ARM_EABI_VER1 0x01000000
+#define EF_ARM_EABI_VER2 0x02000000
+#define EF_ARM_EABI_VER3 0x03000000
+#define EF_ARM_EABI_VER4 0x04000000
+#define EF_ARM_EABI_VER5 0x05000000
#define ELF32_MACHDEP_ID_CASES \
case EM_ARM: \
@@ -32,6 +41,7 @@
#define ELF32_MACHDEP_ID EM_ARM
+#define KERN_ELFSIZE 32
#define ARCH_ELFSIZE 32 /* MD native binary size */
/* Processor specific relocation types */
@@ -46,7 +56,7 @@
#define R_ARM_THM_ABS5 7
#define R_ARM_ABS8 8
#define R_ARM_SBREL32 9
-#define R_ARM_THM_CALL 10
+#define R_ARM_THM_PC22 10
#define R_ARM_THM_PC8 11
#define R_ARM_AMP_VCALL9 12
#define R_ARM_SWI24 13
@@ -68,34 +78,36 @@
#define R_ARM_GOTPC 25
#define R_ARM_GOT32 26
#define R_ARM_PLT32 27
-#define R_ARM_CALL 28
-#define R_ARM_JUMP24 29
+#define R_ARM_CALL 28
+#define R_ARM_JUMP24 29
#define R_ARM_THM_JUMP24 30
-#define R_ARM_BASE_ABS 31
-
+#define R_ARM_BASE_ABS 31
#define R_ARM_ALU_PCREL_7_0 32
#define R_ARM_ALU_PCREL_15_8 33
#define R_ARM_ALU_PCREL_23_15 34
#define R_ARM_ALU_SBREL_11_0 35
#define R_ARM_ALU_SBREL_19_12 36
-#define R_ARM_ALU_SBREL_27_20 37
-#define R_ARM_V4BX 40
-#define R_ARM_TARGET2 41
-#define R_ARM_PREL31 42
-
-#define R_ARM_MOVW_ABS_NC 43
-#define R_ARM_MOVT_ABS 44
-
-#define R_ARM_THM_MOVW_ABS_NC 47
-#define R_ARM_THM_MOVT_ABS 48
-
-#define R_ARM_THM_JUMP19 51
+#define R_ARM_ALU_SBREL_27_20 37 // depcreated
+#define R_ARM_TARGET1 38
+#define R_ARM_SBREL31 39 // deprecated
+#define R_ARM_V4BX 40
+#define R_ARM_TARGET2 41
+#define R_ARM_PREL31 42
+#define R_ARM_MOVW_ABS_NC 43
+#define R_ARM_MOVT_ABS 44
+#define R_ARM_MOVW_PREL_NC 45
+#define R_ARM_MOVT_PREL 46
+#define R_ARM_THM_MOVW_ABS_NC 47
+#define R_ARM_THM_MOVT_ABS 48
+#define R_ARM_THM_MOVW_PREL_NC 49
+#define R_ARM_THM_MOVT_PREL 50
+#define R_ARM_THM_JUMP19 51
/* 96-111 are reserved to G++. */
#define R_ARM_GNU_VTENTRY 100
#define R_ARM_GNU_VTINHERIT 101
-#define R_ARM_THM_JUMP11 102
-#define R_ARM_THM_JUMP8 103
+#define R_ARM_THM_PC11 102
+#define R_ARM_THM_PC9 103
/* More TLS relocations */
#define R_ARM_TLS_GD32 104 /* PC-rel 32 bit for global dynamic */
@@ -109,6 +121,8 @@
/* 112-127 are reserved for private experiments. */
+#define R_ARM_IRELATIVE 160
+
#define R_ARM_RXPC25 249
#define R_ARM_RSBREL32 250
#define R_ARM_THM_RPC22 251
@@ -124,9 +138,27 @@
#define PF_ARM_PI 0x20000000
#define PF_ARM_ENTRY 0x80000000
+/* Processor specific program header types */
+#define PT_ARM_EXIDX (PT_LOPROC + 1)
+
/* Processor specific section header flags */
#define SHF_ENTRYSECT 0x10000000
#define SHF_COMDEF 0x80000000
/* Processor specific symbol types */
#define STT_ARM_TFUNC STT_LOPROC
+
+#ifdef _KERNEL
+#ifdef ELFSIZE
+#define ELF_MD_PROBE_FUNC ELFNAME2(arm_netbsd,probe)
+#define ELF_MD_COREDUMP_SETUP ELFNAME2(arm_netbsd,coredump_setup)
+#endif
+
+struct exec_package;
+
+int arm_netbsd_elf32_probe(struct lwp *, struct exec_package *, void *, char *,
+ vaddr_t *);
+void arm_netbsd_elf32_coredump_setup(struct lwp *, void *);
+#endif
+
+#endif /* _ARM_ELF_MACHDEP_H_ */