[rtems commit] libdl: Fix the support for constructors and desctructors.

Chris Johns chrisj at rtems.org
Fri Feb 8 23:07:58 UTC 2019


Module:    rtems
Branch:    master
Commit:    4408603e27d028c5c735cf5d9d8160807ce1d591
Changeset: http://git.rtems.org/rtems/commit/?id=4408603e27d028c5c735cf5d9d8160807ce1d591

Author:    Chris Johns <chrisj at rtems.org>
Date:      Wed Jan  9 22:14:11 2019 +1100

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

---

 cpukit/include/rtems/rtl/rtl-obj.h                 |  1 +
 cpukit/libdl/rtl-elf.c                             | 21 +++++
 cpukit/libdl/rtl-mdreloc-arm.c                     | 12 +--
 cpukit/libdl/rtl-unresolved.c                      |  4 +-
 cpukit/libdl/rtl.c                                 | 93 ++++++++++++++--------
 cpukit/score/cpu/arm/include/machine/elf_machdep.h | 72 ++++++++++++-----
 testsuites/libtests/dl08/dl-load.c                 |  2 +-
 7 files changed, 145 insertions(+), 60 deletions(-)

diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index bc50388..b7522a7 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 caa37e6..63242ac 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 96e14fc..ef00701 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 4e81c3c..7e2d920 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 f331cbb..a3664c7 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 8f01d05..6196879 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_ */
diff --git a/testsuites/libtests/dl08/dl-load.c b/testsuites/libtests/dl08/dl-load.c
index 3fd3597..615a837 100644
--- a/testsuites/libtests/dl08/dl-load.c
+++ b/testsuites/libtests/dl08/dl-load.c
@@ -126,7 +126,7 @@ int dl_load_test(void)
 
   dl_load_dump ();
 
-  printf ("\n\n\nRunning rtems_main_o1:\n\n");
+  printf ("Running rtems_main_o1:\n");
   if (dl_call (o1, "rtems_main_o1"))
     return 1;
 



More information about the vc mailing list