summaryrefslogtreecommitdiffstats
path: root/cpukit/libdl
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2019-01-09 22:14:11 +1100
committerChris Johns <chrisj@rtems.org>2019-02-09 10:06:34 +1100
commit4408603e27d028c5c735cf5d9d8160807ce1d591 (patch)
treec27bef5ceb630e13724bd11791659c0fae3e0543 /cpukit/libdl
parentlibtest/dl08: Add a test for archives. (diff)
downloadrtems-4408603e27d028c5c735cf5d9d8160807ce1d591.tar.bz2
libdl: Fix the support for constructors and desctructors.
- Fix the handling of pending objects. - Add a constructor flags in objects to track then being called. Closes #2921
Diffstat (limited to 'cpukit/libdl')
-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
4 files changed, 91 insertions, 39 deletions
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..ef00701d32 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 ABS32 */
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);
}