[PATCH 3/3] libdl: Add object file dependencies to track references

chrisj at rtems.org chrisj at rtems.org
Wed Nov 21 06:11:06 UTC 2018


From: Chris Johns <chrisj at rtems.org>

Tracking references lets us manage when an object file can be
unloaded. If an object file has references to it, it cannot be
unloaded.

Modules that depend on each other cannot be unloaded.

Updates #3605
---
 cpukit/include/rtems/rtl/rtl-obj-fwd.h |   6 +
 cpukit/include/rtems/rtl/rtl-obj.h     | 109 ++++++-
 cpukit/include/rtems/rtl/rtl-sym.h     |   4 +-
 cpukit/include/rtems/rtl/rtl.h         |  25 ++
 cpukit/libdl/rtl-elf.c                 | 346 ++++++++++++++++------
 cpukit/libdl/rtl-elf.h                 |  22 --
 cpukit/libdl/rtl-obj.c                 | 141 ++++++++-
 cpukit/libdl/rtl-shell.c               |  54 +++-
 cpukit/libdl/rtl-unresolved.c          |   4 +-
 cpukit/libdl/rtl.c                     |  48 +++-
 testsuites/libtests/Makefile.am        |  40 ++-
 testsuites/libtests/configure.ac       |   1 +
 testsuites/libtests/dl02/dl-load.c     |  11 +-
 testsuites/libtests/dl07/dl-load.c     | 165 +++++++++++
 testsuites/libtests/dl07/dl-load.h     |  21 ++
 testsuites/libtests/dl07/dl-o1.c       |  56 ++++
 testsuites/libtests/dl07/dl-o1.h       |  22 ++
 testsuites/libtests/dl07/dl-o2.c       |  51 ++++
 testsuites/libtests/dl07/dl-o2.h       |  23 ++
 testsuites/libtests/dl07/dl-o3.c       |  59 ++++
 testsuites/libtests/dl07/dl-o4.c       |  53 ++++
 testsuites/libtests/dl07/dl-o4.h       |  27 ++
 testsuites/libtests/dl07/dl-o5.c       |  52 ++++
 testsuites/libtests/dl07/dl-o5.h       |  28 ++
 testsuites/libtests/dl07/dl07.doc      |  27 ++
 testsuites/libtests/dl07/dl07.scn      | 510 +++++++++++++++++++++++++++++++++
 testsuites/libtests/dl07/init.c        |  90 ++++++
 27 files changed, 1853 insertions(+), 142 deletions(-)
 create mode 100644 testsuites/libtests/dl07/dl-load.c
 create mode 100644 testsuites/libtests/dl07/dl-load.h
 create mode 100644 testsuites/libtests/dl07/dl-o1.c
 create mode 100644 testsuites/libtests/dl07/dl-o1.h
 create mode 100644 testsuites/libtests/dl07/dl-o2.c
 create mode 100644 testsuites/libtests/dl07/dl-o2.h
 create mode 100644 testsuites/libtests/dl07/dl-o3.c
 create mode 100644 testsuites/libtests/dl07/dl-o4.c
 create mode 100644 testsuites/libtests/dl07/dl-o4.h
 create mode 100644 testsuites/libtests/dl07/dl-o5.c
 create mode 100644 testsuites/libtests/dl07/dl-o5.h
 create mode 100644 testsuites/libtests/dl07/dl07.doc
 create mode 100644 testsuites/libtests/dl07/dl07.scn
 create mode 100644 testsuites/libtests/dl07/init.c

diff --git a/cpukit/include/rtems/rtl/rtl-obj-fwd.h b/cpukit/include/rtems/rtl/rtl-obj-fwd.h
index 39e28c58e1..6d41483aa2 100644
--- a/cpukit/include/rtems/rtl/rtl-obj-fwd.h
+++ b/cpukit/include/rtems/rtl/rtl-obj-fwd.h
@@ -26,6 +26,12 @@ extern "C" {
 struct rtems_rtl_obj_sect;
 typedef struct rtems_rtl_obj_sect rtems_rtl_obj_sect;
 
+/**
+ * The forward declaration of the obj depends structure.
+ */
+struct rtems_rtl_obj_depends;
+typedef struct rtems_rtl_obj_depends rtems_rtl_obj_depends;
+
 /**
  * The forward declaration of the obj structure.
  */
diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index be77a81c9d..976d6c293f 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -138,13 +138,36 @@ struct rtems_rtl_obj_sect
   int              load_order;  /**< Order we load sections. */
 };
 
+/**
+ * Object file dependents. This is a list of tables of pointers to the object
+ * modules the object file depends on. The table is a list of tables because
+ * unresolved externals can exist when an object file is loaded and resolved
+ * later when the dependent object file is loaded.
+ */
+struct rtems_rtl_obj_depends
+{
+  rtems_chain_node node;        /**< The node's link in the chain. */
+  size_t           dependents;  /**< The number of dependent object pointers. */
+  rtems_rtl_obj*   depends[];   /**< Dependtent objects. More follow. */
+};
+
+/**
+ * Dependency iterator.
+ */
+typedef bool (*rtems_rtl_obj_depends_iterator) (rtems_rtl_obj* obj,
+                                                rtems_rtl_obj* dependent,
+                                                void*          data);
+
 /**
  * Object file descriptor flags.
  */
-#define RTEMS_RTL_OBJ_LOCKED     (1 << 0) /**< Lock the object file so it cannot
-                                           *   be unloaded. */
-#define RTEMS_RTL_OBJ_UNRESOLVED (1 << 1) /**< The object file has unresolved
-                                           *   external symbols. */
+#define RTEMS_RTL_OBJ_LOCKED       (1 << 0) /**< Lock the object file so it cannot
+                                             *   be unloaded. */
+#define RTEMS_RTL_OBJ_UNRESOLVED   (1 << 1) /**< The object file has unresolved
+                                             *   external symbols. */
+#define RTEMS_RTL_OBJ_BASE         (1 << 2) /**< The base image. */
+#define RTEMS_RTL_OBJ_RELOC_TAG    (1 << 3) /**< Tag the object as visited when reloc
+                                             *   parsing. */
 
 /**
  * RTL Object. There is one for each object module loaded plus one for the base
@@ -154,7 +177,8 @@ struct rtems_rtl_obj
 {
   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. */
+  size_t              users;        /**< Users of this object file, number of loads. */
+  size_t              refs;         /**< 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
@@ -164,27 +188,28 @@ struct rtems_rtl_obj
                                      *   in a lib */
   off_t               ooffset;      /**< The object offset in the archive. */
   size_t              fsize;        /**< Size of the object file. */
-  rtems_chain_control sections;     /**< The sections of interest in the
-                                     *   object file. */
+  rtems_chain_control sections;     /**< The sections of interest in the object
+                                     *   file. */
+  rtems_chain_control dependents;   /**< The dependent object files. */
   rtems_rtl_obj_sym*  local_table;  /**< Local symbol table. */
   size_t              local_syms;   /**< Local symbol count. */
   size_t              local_size;   /**< Local symbol memory usage. */
   rtems_rtl_obj_sym*  global_table; /**< Global symbol table. */
   size_t              global_syms;  /**< Global symbol count. */
   size_t              global_size;  /**< Global symbol memory usage. */
-  uint32_t            unresolved;   /**< The number of unresolved relocations. */
+  size_t              unresolved;   /**< The number of unresolved relocations. */
   void*               text_base;    /**< The base address of the text section
                                      *   in memory. */
   size_t              text_size;    /**< The size of the text section. */
   void*               const_base;   /**< The base address of the const section
                                      *   in memory. */
-  void*               eh_base;      /**< The base address of the eh section
-                                     *   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. */
-  void*               bss_base;     /**< The base address of the bss section
-                                     *   in memory. */
+  void*               bss_base;     /**< The base address of the bss section in
+                                     *   memory. */
   size_t              bss_size;     /**< The size of the bss section. */
   size_t              exec_size;    /**< The amount of executable memory
                                      *   allocated */
@@ -192,9 +217,11 @@ struct rtems_rtl_obj
   uint32_t            checksum;     /**< The checksum of the text sections. A
                                      *   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. */
+  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. */
+  void*               loader;       /**< The file details specific to a
+                                     *   loader. */
 };
 
 /**
@@ -442,6 +469,46 @@ rtems_rtl_obj_sect* rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj
                                                         int                  index,
                                                         uint32_t             mask);
 
+/**
+ * Allocate a table for dependent objects.
+ *
+ * @param obj The object file's descriptor.
+ * @param dependents The size of the table.
+ * @retval true The table was allocated.
+ * @retval false The alloction failed.
+ */
+bool rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents);
+
+/**
+ * Erase the object file descriptor's dependents.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj);
+
+/**
+ * Add an object file to the dependents table.
+ *
+ * @param obj The object file's descriptor.
+ * @param dependent The dependent object file to add.
+ * @retval true The dependent has been added to the table.
+ * @retval false There is no space in the table.
+ */
+bool rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent);
+
+/**
+ * Iterate over the module dependenices.
+ *
+ * @param obj The object file's descriptor.
+ * @param handler The iterator handler. Returns true to end.
+ * @param data User data passed to the iterator.
+ * @retval true The iterator handler returned true.
+ * @retval false The iterator handler returned false.
+ */
+bool rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
+                                       rtems_rtl_obj_depends_iterator iterator,
+                                       void*                          data);
+
 /**
  * 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
@@ -642,6 +709,20 @@ void rtems_rtl_obj_run_ctors (rtems_rtl_obj* obj);
  */
 void rtems_rtl_obj_run_dtors (rtems_rtl_obj* obj);
 
+/**
+ * Increment the object file reference count.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj);
+
+/**
+ * Decrement the object file reference count.
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj);
+
 /**
  * Load the object file, reading all sections into memory, symbols and
  * performing any relocation fixups.
diff --git a/cpukit/include/rtems/rtl/rtl-sym.h b/cpukit/include/rtems/rtl/rtl-sym.h
index be246a908d..aff9339ea1 100644
--- a/cpukit/include/rtems/rtl/rtl-sym.h
+++ b/cpukit/include/rtems/rtl/rtl-sym.h
@@ -92,7 +92,7 @@ bool rtems_rtl_symbol_global_add (rtems_rtl_obj*       obj,
  *
  * @param name The name as an ASCIIZ string.
  * @retval NULL No symbol found.
- * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ * @return rtems_rtl_obj_sym* Reference to the symbol.
  */
 rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
 
@@ -102,7 +102,7 @@ rtems_rtl_obj_sym* rtems_rtl_symbol_global_find (const char* name);
  * @param obj The object file to search.
  * @param name The name as an ASCIIZ string.
  * @retval NULL No symbol found.
- * @return rtems_rtl_obj_sym_t* Reference to the symbol.
+ * @return rtems_rtl_obj_sym* Reference to the symbol.
  */
 rtems_rtl_obj_sym* rtems_rtl_symbol_obj_find (rtems_rtl_obj* obj,
                                               const char*    name);
diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h
index e30dba90ef..398ac2cd3f 100644
--- a/cpukit/include/rtems/rtl/rtl.h
+++ b/cpukit/include/rtems/rtl/rtl.h
@@ -28,6 +28,7 @@
 #include <rtems/rtl/rtl-obj.h>
 #include <rtems/rtl/rtl-obj-cache.h>
 #include <rtems/rtl/rtl-obj-comp.h>
+#include <rtems/rtl/rtl-sym.h>
 #include <rtems/rtl/rtl-unresolved.h>
 
 #ifdef __cplusplus
@@ -70,6 +71,11 @@ extern "C" {
  */
 #define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
 
+/**
+ * The number of dependency record per block in the dependency table.
+ */
+#define RTEMS_RTL_DEPENDENCY_BLOCK_SIZE (16)
+
 /**
  * The global debugger interface variable.
  */
@@ -172,6 +178,16 @@ void rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp,
                                int                  compression,
                                off_t                offset);
 
+/**
+ * Update the mask in the object files. You can clear flags and then set
+ * flags. A zero (0) does not clear or set the flags. This is global to all
+ * object files that are laoded.
+ *
+ * @param clear The flag's clear mask, a 0 does not clear any flags.
+ * @param set The flag's set mask, a 0 does not set any flags.
+ */
+void rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set);
+
 /**
  * Lock the Run-time Linker.
  *
@@ -206,6 +222,15 @@ rtems_rtl_obj* rtems_rtl_check_handle (void* handle);
  */
 rtems_rtl_obj* rtems_rtl_find_obj (const char* name);
 
+/**
+ * Find the object file a symbol is exported from.
+ *
+ * @param sym The symbol to search with.
+ * @retval NULL No object file found.
+ * @return rtems_rtl_obj* Reference to the symbol.
+ */
+rtems_rtl_obj* rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym);
+
 /**
  * Load an object file into memory relocating it. It will not be resolved
  * against other symbols in other object files or the base image.
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index c1821bcfda..0327fd6308 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -64,31 +64,40 @@ rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
   return true;
 }
 
-bool
-rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
-                           const Elf_Sym* sym,
-                           const char*    symname,
-                           Elf_Word*      value)
+static bool
+rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
+                           const Elf_Sym*      sym,
+                           const char*         symname,
+                           rtems_rtl_obj_sym** symbol,
+                           Elf_Word*           value)
 {
   rtems_rtl_obj_sect* sect;
 
-  if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE ||
-      sym->st_shndx == SHN_COMMON)
+  /*
+   * If the symbol type is STT_NOTYPE the symbol references a global
+   * symbol. The gobal symbol table is searched to find it and that value
+   * returned. If the symbol is local to the object module the section for the
+   * symbol is located and it's base added to the symbol's value giving an
+   * absolute location.
+   */
+  if (ELF_ST_TYPE(sym->st_info) == STT_NOTYPE || sym->st_shndx == SHN_COMMON)
   {
     /*
      * Search the object file then the global table for the symbol.
      */
-    rtems_rtl_obj_sym* symbol = rtems_rtl_symbol_obj_find (obj, symname);
-    if (!symbol)
+    *symbol = rtems_rtl_symbol_obj_find (obj, symname);
+    if (!*symbol)
     {
       rtems_rtl_set_error (EINVAL, "global symbol not found: %s", symname);
       return false;
     }
 
-    *value = (Elf_Addr) symbol->value;
+    *value = (Elf_Addr) (*symbol)->value;
     return true;
   }
 
+  *symbol = NULL;
+
   sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
   if (!sect)
   {
@@ -100,11 +109,161 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
   return true;
 }
 
+/**
+ * Relocation worker routine.
+ */
+typedef bool (*rtems_rtl_elf_reloc_handler)(rtems_rtl_obj*      obj,
+                                            bool                is_rela,
+                                            void*               relbuf,
+                                            rtems_rtl_obj_sect* targetsect,
+                                            rtems_rtl_obj_sym*  symbol,
+                                            Elf_Sym*            sym,
+                                            const char*         symname,
+                                            Elf_Word            symvalue,
+                                            bool                resolved,
+                                            void*               data);
+
+/**
+ * Relocation parser data.
+ */
+typedef struct
+{
+  size_t dependents; /**< The number of dependent object files. */
+  size_t unresolved; /**< The number of unresolved symbols. */
+} rtems_rtl_elf_reloc_data;
+
+static bool
+rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
+                            bool                is_rela,
+                            void*               relbuf,
+                            rtems_rtl_obj_sect* targetsect,
+                            rtems_rtl_obj_sym*  symbol,
+                            Elf_Sym*            sym,
+                            const char*         symname,
+                            Elf_Word            symvalue,
+                            bool                resolved,
+                            void*               data)
+{
+  rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
+  /*
+   * If the symbol has been resolved and there is a symbol name it is a global
+   * symbol and from another object file so add it as a dependency.
+   */
+  if (!resolved)
+  {
+    ++rd->unresolved;
+  }
+  else if (resolved && symname != NULL)
+  {
+    /*
+     * Find the symbol's object file. It cannot be NULL so ignore that result
+     * if returned, it means something is corrupted. We are in an iterator.
+     */
+    rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
+    if (sobj != NULL)
+    {
+      /*
+       * A dependency is not the base kernel image or itself. Tag the object as
+       * having been visited so we count it only once.
+       */
+      if (sobj != rtems_rtl_baseimage () && obj != sobj &&
+          (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
+      {
+        sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
+        ++rd->dependents;
+      }
+    }
+  }
+  return true;
+}
+
+static bool
+rtems_rtl_elf_reloc_relocator (rtems_rtl_obj*      obj,
+                               bool                is_rela,
+                               void*               relbuf,
+                               rtems_rtl_obj_sect* targetsect,
+                               rtems_rtl_obj_sym*  symbol,
+                               Elf_Sym*            sym,
+                               const char*         symname,
+                               Elf_Word            symvalue,
+                               bool                resolved,
+                               void*               data)
+{
+  const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+  const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
+
+  if (!resolved)
+  {
+    uint16_t       flags = 0;
+    rtems_rtl_word rel_words[3];
+
+    if (is_rela)
+    {
+      flags = 1;
+      rel_words[REL_R_OFFSET] = rela->r_offset;
+      rel_words[REL_R_INFO] = rela->r_info;
+      rel_words[REL_R_ADDEND] = rela->r_addend;
+    }
+    else
+    {
+      rel_words[REL_R_OFFSET] = rel->r_offset;
+      rel_words[REL_R_INFO] = rel->r_info;
+      rel_words[REL_R_ADDEND] = 0;
+    }
+
+    if (!rtems_rtl_unresolved_add (obj,
+                                   flags,
+                                   symname,
+                                   targetsect->section,
+                                   rel_words))
+      return false;
+
+    ++obj->unresolved;
+  }
+  else
+  {
+    rtems_rtl_obj* sobj;
+
+    if (is_rela)
+    {
+      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+        printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
+                symname, (int) ELF_R_SYM (rela->r_info),
+                (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
+                (uintmax_t) rela->r_offset, (int) rela->r_addend);
+      if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
+                                        symname, sym->st_info, symvalue))
+        return false;
+    }
+    else
+    {
+      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+        printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
+                symname, (int) ELF_R_SYM (rel->r_info),
+                (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
+                (uintmax_t) rel->r_offset);
+      if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
+                                       symname, sym->st_info, symvalue))
+        return false;
+    }
+
+    sobj = rtems_rtl_find_obj_with_symbol (symbol);
+    if (sobj != NULL)
+    {
+      if (rtems_rtl_obj_add_dependent (obj, sobj))
+        rtems_rtl_obj_inc_reference (sobj);
+    }
+  }
+
+  return true;
+}
+
 static bool
-rtems_rtl_elf_relocator (rtems_rtl_obj*      obj,
-                         int                 fd,
-                         rtems_rtl_obj_sect* sect,
-                         void*               data)
+rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
+                               int                         fd,
+                               rtems_rtl_obj_sect*         sect,
+                               rtems_rtl_elf_reloc_handler handler,
+                               void*                       data)
 {
   rtems_rtl_obj_cache* symbols;
   rtems_rtl_obj_cache* strings;
@@ -155,15 +314,16 @@ rtems_rtl_elf_relocator (rtems_rtl_obj*      obj,
 
   for (reloc = 0; reloc < (sect->size / reloc_size); ++reloc)
   {
-    uint8_t         relbuf[reloc_size];
-    const Elf_Rela* rela = (const Elf_Rela*) relbuf;
-    const Elf_Rel*  rel = (const Elf_Rel*) relbuf;
-    Elf_Sym         sym;
-    const char*     symname = NULL;
-    off_t           off;
-    Elf_Word        type;
-    Elf_Word        symvalue = 0;
-    bool            relocate;
+    uint8_t            relbuf[reloc_size];
+    const Elf_Rela*    rela = (const Elf_Rela*) relbuf;
+    const Elf_Rel*     rel = (const Elf_Rel*) relbuf;
+    rtems_rtl_obj_sym* symbol = NULL;
+    Elf_Sym            sym;
+    const char*        symname = NULL;
+    off_t              off;
+    Elf_Word           rel_type;
+    Elf_Word           symvalue = 0;
+    bool               resolved;
 
     off = obj->ooffset + sect->offset + (reloc * reloc_size);
 
@@ -203,75 +363,26 @@ rtems_rtl_elf_relocator (rtems_rtl_obj*      obj,
     /*
      * See if the record references an external symbol. If it does find the
      * symbol value. If the symbol cannot be found flag the object file as
-     * having unresolved externals and store the externals. The load of an
+     * having unresolved externals and store the external. The load of an
      * object after this one may provide the unresolved externals.
      */
     if (is_rela)
-      type = ELF_R_TYPE(rela->r_info);
+      rel_type = ELF_R_TYPE(rela->r_info);
     else
-      type = ELF_R_TYPE(rel->r_info);
-
-    relocate = true;
-
-    if (rtems_rtl_elf_rel_resolve_sym (type))
-    {
-      if (!rtems_rtl_elf_find_symbol (obj, &sym, symname, &symvalue))
-      {
-        uint16_t       flags = 0;
-        rtems_rtl_word rel_words[3];
-
-        relocate = false;
-
-        if (is_rela)
-        {
-          flags = 1;
-          rel_words[REL_R_OFFSET] = rela->r_offset;
-          rel_words[REL_R_INFO] = rela->r_info;
-          rel_words[REL_R_ADDEND] = rela->r_addend;
-        }
-        else
-        {
-          rel_words[REL_R_OFFSET] = rel->r_offset;
-          rel_words[REL_R_INFO] = rel->r_info;
-          rel_words[REL_R_ADDEND] = 0;
-        }
+      rel_type = ELF_R_TYPE(rel->r_info);
 
-        if (!rtems_rtl_unresolved_add (obj,
-                                       flags,
-                                       symname,
-                                       targetsect->section,
-                                       rel_words))
-          return false;
+    resolved = true;
 
-        ++obj->unresolved;
-      }
-    }
+    if (rtems_rtl_elf_rel_resolve_sym (rel_type))
+      resolved = rtems_rtl_elf_find_symbol (obj,
+                                            &sym, symname,
+                                            &symbol, &symvalue);
 
-    if (relocate)
-    {
-      if (is_rela)
-      {
-        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-          printf ("rtl: rela: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
-                  symname, (int) ELF_R_SYM (rela->r_info),
-                  (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
-                  (uintmax_t) rela->r_offset, (int) rela->r_addend);
-        if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
-                                          symname, sym.st_info, symvalue))
-          return false;
-      }
-      else
-      {
-        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-          printf ("rtl: rel: sym:%s(%d)=%08jx type:%d off:%08jx\n",
-                  symname, (int) ELF_R_SYM (rel->r_info),
-                  (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
-                  (uintmax_t) rel->r_offset);
-        if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
-                                         symname, sym.st_info, symvalue))
-          return false;
-      }
-    }
+    if (!handler (obj,
+                  is_rela, relbuf, targetsect,
+                  symbol, &sym, symname, symvalue, resolved,
+                  data))
+      return false;
   }
 
   /*
@@ -283,6 +394,28 @@ rtems_rtl_elf_relocator (rtems_rtl_obj*      obj,
   return true;
 }
 
+static bool
+rtems_rtl_elf_relocs_parser (rtems_rtl_obj*      obj,
+                             int                 fd,
+                             rtems_rtl_obj_sect* sect,
+                             void*               data)
+{
+  bool r = rtems_rtl_elf_relocate_worker (obj, fd, sect,
+                                          rtems_rtl_elf_reloc_parser, data);
+  rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_RELOC_TAG, 0);
+  return r;
+}
+
+static bool
+rtems_rtl_elf_relocs_locator (rtems_rtl_obj*      obj,
+                              int                 fd,
+                              rtems_rtl_obj_sect* sect,
+                              void*               data)
+{
+  return rtems_rtl_elf_relocate_worker (obj, fd, sect,
+                                        rtems_rtl_elf_reloc_relocator, data);
+}
+
 bool
 rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
                                    rtems_rtl_obj_sym*        sym)
@@ -290,8 +423,9 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
   rtems_rtl_obj_sect* sect;
   bool                is_rela;
   Elf_Word            symvalue;
+  rtems_rtl_obj*      sobj;
 
-  is_rela =reloc->flags & 1;
+  is_rela = reloc->flags & 1;
 
   sect = rtems_rtl_obj_find_section_by_index (reloc->obj, reloc->sect);
   if (!sect)
@@ -329,13 +463,20 @@ rtems_rtl_obj_relocate_unresolved (rtems_rtl_unresolv_reloc* reloc,
       return false;
   }
 
-  if (reloc->obj->unresolved)
+  if (reloc->obj->unresolved > 0)
   {
     --reloc->obj->unresolved;
-    if (!reloc->obj->unresolved)
+    if (reloc->obj->unresolved == 0)
       reloc->obj->flags &= ~RTEMS_RTL_OBJ_UNRESOLVED;
   }
 
+  sobj = rtems_rtl_find_obj_with_symbol (sym);
+  if (sobj != NULL)
+  {
+    if (rtems_rtl_obj_add_dependent (reloc->obj, sobj))
+      rtems_rtl_obj_inc_reference (sobj);
+  }
+
   return true;
 }
 
@@ -401,6 +542,24 @@ rtems_rtl_elf_common (rtems_rtl_obj*      obj,
   return true;
 }
 
+static bool
+rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
+{
+  /*
+   * If there are dependencies and no unresolved externals allocate and size
+   * the dependency table to the number of dependent object files. If there are
+   * unresolved externals the number of dependencies is unknown at this point
+   * in time so use dynamic allocation to allocate the block size number of
+   * entried when the entries are added.
+   */
+  if (reloc->dependents > 0 && reloc->unresolved == 0)
+  {
+    if (!rtems_rtl_obj_alloc_dependents (obj, reloc->dependents))
+      return false;
+  }
+  return true;
+}
+
 static bool
 rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
                        int                 fd,
@@ -1024,7 +1183,8 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
 {
   rtems_rtl_obj_cache*      header;
   Elf_Ehdr                  ehdr;
-  rtems_rtl_elf_common_data common = { .size = 0, .alignment = 0 };
+  rtems_rtl_elf_reloc_data  relocs = { 0 };
+  rtems_rtl_elf_common_data common = { 0 };
 
   rtems_rtl_obj_caches (&header, NULL, NULL);
 
@@ -1102,10 +1262,16 @@ rtems_rtl_elf_file_load (rtems_rtl_obj* obj, int fd)
   if (!rtems_rtl_obj_load_sections (obj, fd, rtems_rtl_elf_loader, &ehdr))
     return false;
 
+  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_parser, &relocs))
+    return false;
+
+  if (!rtems_rtl_elf_dependents (obj, &relocs))
+    return false;
+
   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
     return false;
 
-  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocator, &ehdr))
+  if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
     return false;
 
   rtems_rtl_obj_synchronize_cache (obj);
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index 5d560a0b34..1f5f82eb89 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -122,28 +122,6 @@ bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
                                   const Elf_Byte            syminfo,
                                   const Elf_Word            symvalue);
 
-/**
- * Find the symbol. The symbol is passed as an ELF type symbol with the name
- * and the value returned is the absolute address of the symbol.
- *
- * If the symbol type is STT_NOTYPE the symbol references a global symbol. The
- * gobal symbol table is searched to find it and that value returned. If the
- * symbol is local to the object module the section for the symbol is located
- * and it's base added to the symbol's value giving an absolute location.
- *
- * @param obj The object the symbol is being resolved for.
- * @param sym The ELF type symbol.
- * @param symname The sym's name read from the symbol string table.
- * @param value Return the value of the symbol. Only valid if the return value
- *              is true.
- * @retval true The symbol resolved.
- * @retval false The symbol could not be result. The RTL error is set.
- */
-bool rtems_rtl_elf_find_symbol (rtems_rtl_obj* obj,
-                                const Elf_Sym* sym,
-                                const char*    symname,
-                                Elf_Word*      value);
-
 /**
  * The ELF format check handler.
  *
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 7109b86fe8..0f58bf9bda 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -83,6 +83,7 @@ rtems_rtl_obj_alloc (void)
      * Initialise the chains.
      */
     rtems_chain_initialize_empty (&obj->sections);
+    rtems_chain_initialize_empty (&obj->dependents);
     /*
      * No valid format.
      */
@@ -114,6 +115,8 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj)
     rtems_chain_extract (&obj->link);
   rtems_rtl_alloc_module_del (&obj->text_base, &obj->const_base, &obj->eh_base,
                               &obj->data_base, &obj->bss_base);
+  rtems_rtl_obj_erase_sections (obj);
+  rtems_rtl_obj_erase_dependents (obj);
   rtems_rtl_symbol_obj_erase (obj);
   rtems_rtl_obj_free_names (obj);
   if (obj->sec_num)
@@ -550,6 +553,110 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
   return match.sect;
 }
 
+bool
+rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
+{
+  rtems_rtl_obj_depends* depends;
+  size_t                 size;
+
+  size = sizeof (rtems_rtl_obj_depends) + sizeof (rtems_rtl_obj*) * dependents;
+
+  depends = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+                                 size,
+                                 true);
+  if (depends == NULL)
+  {
+    rtems_rtl_set_error (ENOMEM, "no memory for the dependency");
+  }
+  else
+  {
+    depends->dependents = dependents;
+    rtems_chain_append (&obj->dependents, &depends->node);
+  }
+
+  return depends != NULL;
+}
+
+void
+rtems_rtl_obj_erase_dependents (rtems_rtl_obj* obj)
+{
+  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
+  while (!rtems_chain_is_tail (&obj->dependents, node))
+  {
+    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+    rtems_chain_node*      next_node = rtems_chain_next (node);
+    rtems_chain_extract (node);
+    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, depends);
+    node = next_node;
+  }
+}
+
+bool
+rtems_rtl_obj_add_dependent (rtems_rtl_obj* obj, rtems_rtl_obj* dependent)
+{
+  rtems_rtl_obj**   free_slot;
+  rtems_chain_node* node;
+  if (obj == dependent || dependent == rtems_rtl_baseimage ())
+    return false;
+  free_slot = NULL;
+  node = rtems_chain_first (&obj->dependents);
+  while (!rtems_chain_is_tail (&obj->dependents, node))
+  {
+    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+    size_t                 d;
+    for (d = 0; d < depends->dependents; ++d)
+    {
+      if (free_slot == NULL && depends->depends[d] == NULL)
+        free_slot = &(depends->depends[d]);
+      if (depends->depends[d] == dependent)
+        return false;
+    }
+    node = rtems_chain_next (node);
+  }
+  if (free_slot == NULL)
+  {
+    if (rtems_rtl_obj_alloc_dependents (obj,
+                                        RTEMS_RTL_DEPENDENCY_BLOCK_SIZE))
+    {
+      rtems_rtl_obj_depends* depends;
+      node = rtems_chain_last (&obj->dependents);
+      depends = (rtems_rtl_obj_depends*) node;
+      free_slot = &(depends->depends[0]);
+      if (*free_slot != NULL)
+      {
+        rtems_rtl_set_error (EINVAL, "new dependency node not empty");
+        free_slot = NULL;
+      }
+    }
+  }
+  if (free_slot != NULL)
+    *free_slot = dependent;
+  return free_slot != NULL;
+}
+
+bool
+rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
+                                  rtems_rtl_obj_depends_iterator iterator,
+                                  void*                          data)
+{
+  rtems_chain_node* node = rtems_chain_first (&obj->dependents);
+  while (!rtems_chain_is_tail (&obj->dependents, node))
+  {
+    rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+    size_t                 d;
+    for (d = 0; d < depends->dependents; ++d)
+    {
+      if (depends->depends[d])
+      {
+        if (iterator (obj, depends->depends[d], data))
+          return true;
+      }
+    }
+    node = rtems_chain_next (node);
+  }
+  return false;
+}
+
 size_t
 rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
 {
@@ -1220,10 +1327,42 @@ static bool
 rtems_rtl_obj_file_unload (rtems_rtl_obj* obj)
 {
   if (obj->format >= 0 && obj->format < RTEMS_RTL_LOADERS)
-      return loaders[obj->format].unload (obj);
+  {
+    rtems_chain_node* node;
+
+    if (!loaders[obj->format].unload (obj))
+      return false;
+
+    node = rtems_chain_first (&obj->dependents);
+    while (!rtems_chain_is_tail (&obj->dependents, node))
+    {
+      rtems_rtl_obj_depends* depends = (rtems_rtl_obj_depends*) node;
+      size_t                 d;
+      for (d = 0; d < depends->dependents; ++d)
+      {
+        if (depends->depends[d] != NULL)
+          rtems_rtl_obj_dec_reference (depends->depends[d]);
+      }
+      node = rtems_chain_next (node);
+    }
+  }
+
   return false;
 }
 
+void
+rtems_rtl_obj_inc_reference (rtems_rtl_obj* obj)
+{
+  ++obj->refs;
+}
+
+void
+rtems_rtl_obj_dec_reference (rtems_rtl_obj* obj)
+{
+  if (obj->refs)
+    --obj->refs;
+}
+
 bool
 rtems_rtl_obj_load (rtems_rtl_obj* obj)
 {
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index 5c144977a0..f3471d8d8e 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -117,13 +117,14 @@ rtems_rtl_shell_status (rtems_rtl_data* rtl, int argc, char *argv[])
  */
 typedef struct
 {
-  rtems_rtl_data* rtl;        /**< The RTL data. */
-  int             indent;     /**< Spaces to indent. */
-  bool            oname;      /**< Print object names. */
-  bool            names;      /**< Print details of all names. */
-  bool            memory_map; /**< Print the memory map. */
-  bool            symbols;    /**< Print the global symbols. */
-  bool            base;       /**< Include the base object file. */
+  rtems_rtl_data* rtl;          /**< The RTL data. */
+  int             indent;       /**< Spaces to indent. */
+  bool            oname;        /**< Print object names. */
+  bool            names;        /**< Print details of all names. */
+  bool            memory_map;   /**< Print the memory map. */
+  bool            symbols;      /**< Print the global symbols. */
+  bool            dependencies; /**< Print any dependencies. */
+  bool            base;         /**< Include the base object file. */
 } rtems_rtl_obj_print;
 
 /**
@@ -168,6 +169,29 @@ rtems_rtl_symbols_arg (int argc, char *argv[])
   return rtems_rtl_parse_arg ("-s", argc, argv);
 }
 
+/**
+ * Dependenncies printer.
+ */
+typedef struct
+{
+  bool   first;   /**< Is this the first line printed. */
+  size_t indent;  /**< The indent. */
+} rtems_rtl_dep_data;
+
+static bool
+rtems_rtl_dependencies (rtems_rtl_obj* obj,
+                        rtems_rtl_obj* dependent,
+                        void*          data)
+{
+  rtems_rtl_dep_data* dd = (rtems_rtl_dep_data*) data;
+  if (!dd->first)
+    printf ("\n%-*c: ", dd->indent, ' ');
+  else
+    dd->first = false;
+  printf ("%s", dependent->oname);
+  return false;
+}
+
 /**
  * Object printer.
  */
@@ -214,7 +238,9 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
     printf ("%-*cbss base      : %p (%zi)\n", print->indent, ' ',
             obj->bss_base, obj->bss_size);
   }
-  printf ("%-*cunresolved    : %" PRIu32 "\n", print->indent, ' ', obj->unresolved);
+  printf ("%-*cunresolved    : %zu\n", print->indent, ' ', obj->unresolved);
+  printf ("%-*cusers         : %zu\n", print->indent, ' ', obj->users);
+  printf ("%-*creferences    : %zu\n", print->indent, ' ', obj->refs);
   printf ("%-*csymbols       : %zi\n", print->indent, ' ', obj->global_syms);
   printf ("%-*csymbol memory : %zi\n", print->indent, ' ', obj->global_size);
   if (print->symbols)
@@ -231,6 +257,16 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
       printf ("%-*c%-*s = %p\n", print->indent + 2, ' ',
               max_len, obj->global_table[s].name, obj->global_table[s].value);
   }
+  if (print->dependencies)
+  {
+    rtems_rtl_dep_data dd = {
+      .first = true,
+      .indent = strlen ("dependencies :") + print->indent
+    };
+    printf ("%-*cdependencies  : ", print->indent, ' ');
+    rtems_rtl_obj_iterate_dependents (obj, rtems_rtl_dependencies, &dd);
+    printf ("\n");
+  }
   printf ("\n");
   return true;
 }
@@ -269,6 +305,7 @@ rtems_rtl_shell_list (rtems_rtl_data* rtl, int argc, char *argv[])
   print.names = true;
   print.memory_map = true;
   print.symbols = rtems_rtl_symbols_arg (argc, argv);
+  print.dependencies = true;
   print.base = false;
   rtems_rtl_chain_iterate (&rtl->objects,
                            rtems_rtl_obj_print_iterator,
@@ -286,6 +323,7 @@ rtems_rtl_shell_sym (rtems_rtl_data* rtl, int argc, char *argv[])
   print.names = false;
   print.memory_map = false;
   print.symbols = true;
+  print.dependencies = false;
   print.base = rtems_rtl_base_arg (argc, argv);
   rtems_rtl_chain_iterate (&rtl->objects,
                            rtems_rtl_obj_print_iterator,
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index a3a7e3fba3..dfd9fd793d 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -171,7 +171,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
     rtems_rtl_unresolved_reloc_data* rd;
     rd = (rtems_rtl_unresolved_reloc_data*) data;
 
-    if (rec->rec.reloc.name == rd->name)
+    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);
@@ -185,7 +185,7 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
        * names with a reference count of 0.
        */
       rec->rec.reloc.obj = NULL;
-      if (rd->name_rec && rd->name_rec->rec.name.refs)
+      if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
         --rd->name_rec->rec.name.refs;
     }
   }
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
index 628fc771bc..fdf4c1229f 100644
--- a/cpukit/libdl/rtl.c
+++ b/cpukit/libdl/rtl.c
@@ -216,6 +216,11 @@ rtems_rtl_data_init (void)
        */
       rtl->base->oname = rtems_rtl_strdup ("rtems-kernel");
 
+      /*
+       * Lock the base image and flag it as the base image.
+       */
+      rtl->base->flags |= RTEMS_RTL_OBJ_LOCKED | RTEMS_RTL_OBJ_BASE;
+
       rtems_chain_append (&rtl->objects, &rtl->base->link);
     }
 
@@ -312,6 +317,21 @@ rtems_rtl_obj_decompress (rtems_rtl_obj_comp** decomp,
   }
 }
 
+void
+rtems_rtl_obj_update_flags (uint32_t clear, uint32_t set)
+{
+  rtems_chain_node* node  = rtems_chain_first (&rtl->objects);
+  while (!rtems_chain_is_tail (&rtl->objects, node))
+  {
+    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+    if (clear != 0)
+      obj->flags &= ~clear;
+    if (set != 0)
+      obj->flags |= set;
+    node = rtems_chain_next (node);
+  }
+}
+
 rtems_rtl_data*
 rtems_rtl_lock (void)
 {
@@ -385,6 +405,21 @@ rtems_rtl_find_obj (const char* name)
   return found;
 }
 
+rtems_rtl_obj*
+rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
+{
+  rtems_chain_node* node = rtems_chain_first (&rtl->objects);
+  while (!rtems_chain_is_tail (&rtl->objects, node))
+  {
+    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+    if (sym >= obj->global_table &&
+        sym < (obj->global_table + obj->global_syms))
+      return obj;
+    node = rtems_chain_next (node);
+  }
+  return NULL;
+}
+
 rtems_rtl_obj*
 rtems_rtl_load_object (const char* name, int mode)
 {
@@ -489,6 +524,11 @@ rtems_rtl_unload_object (rtems_rtl_obj* obj)
 
   if (obj->users == 0)
   {
+    if (obj->refs != 0)
+    {
+      rtems_rtl_set_error (EBUSY, "object file referenced");
+      return false;
+    }
     obj->flags |= RTEMS_RTL_OBJ_LOCKED;
     rtems_rtl_unlock ();
     rtems_rtl_obj_run_dtors (obj);
@@ -618,5 +658,11 @@ rtems_rtl_base_sym_global_add (const unsigned char* esyms,
 rtems_rtl_obj*
 rtems_rtl_baseimage (void)
 {
-  return NULL;
+  rtems_rtl_obj* base = NULL;
+  if (rtems_rtl_lock ())
+  {
+    base = rtl->base;
+    rtems_rtl_unlock ();
+  }
+  return base;
 }
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 9e3d2143d6..810f65db8e 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -512,6 +512,45 @@ CLEANFILES += dl06.pre dl06-sym.o dl06-o1.o dl06-o2.o dl06.tar dl06-tar.h
 endif
 endif
 
+if DLTESTS
+if TEST_dl07
+lib_tests += dl07
+lib_screens += dl07/dl07.scn
+lib_docs += dl07/dl07.doc
+dl07_SOURCES = dl07/init.c dl07/dl-load.c dl07-tar.c dl07-tar.h
+dl07_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl07) $(support_includes)
+dl07/init.c: dl07-tar.o
+dl07.pre: $(dl07_OBJECTS) $(dl07_DEPENDENCIES)
+	@rm -f dl07.pre
+	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+dl07-o1.o: dl07/dl-o1.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o2.o: dl07/dl-o2.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o3.o: dl07/dl-o3.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o4.o: dl07/dl-o4.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-o5.o: dl07/dl-o5.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07.tar: dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o
+	@rm -f $@
+	$(AM_V_GEN)$(PAX) -w -f $@ $+
+dl07-tar.c: dl07.tar
+	$(AM_V_GEN)$(BIN2C) -C $< $@
+dl07-tar.h: dl07.tar
+	$(AM_V_GEN)$(BIN2C) -H $< $@
+dl07-tar.o: dl07-tar.c dl07-tar.h
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl07-sym.o: dl07.pre
+	$(AM_V_GEN)rtems-syms -e -c "$(CFLAGS)" -o $@ $<
+dl07$(EXEEXT):  $(dl07_OBJECTS) $(dl07_DEPENDENCIES) dl07-sym.o
+	@rm -f $@
+	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+CLEANFILES += dl07.pre dl07-sym.o dl07-o1.o dl07-o2.o dl07-o3.o dl07-o4.o dl07-o5.o dl07.tar dl07-tar.h
+endif
+endif
+
 if TEST_dumpbuf01
 lib_tests += dumpbuf01
 lib_screens += dumpbuf01/dumpbuf01.scn
@@ -1358,4 +1397,3 @@ endif
 
 rtems_tests_PROGRAMS = $(lib_tests)
 dist_rtems_tests_DATA = $(lib_screens) $(lib_docs)
-
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index 303a165731..a2a0df01f1 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -131,6 +131,7 @@ RTEMS_TEST_CHECK([dl03])
 RTEMS_TEST_CHECK([dl04])
 RTEMS_TEST_CHECK([dl05])
 RTEMS_TEST_CHECK([dl06])
+RTEMS_TEST_CHECK([dl07])
 RTEMS_TEST_CHECK([dumpbuf01])
 RTEMS_TEST_CHECK([dup2])
 RTEMS_TEST_CHECK([exit01])
diff --git a/testsuites/libtests/dl02/dl-load.c b/testsuites/libtests/dl02/dl-load.c
index 601d62113c..a00581ab42 100644
--- a/testsuites/libtests/dl02/dl-load.c
+++ b/testsuites/libtests/dl02/dl-load.c
@@ -12,6 +12,11 @@
 
 #include "dl-load.h"
 
+#include <rtems/rtl/rtl-trace.h>
+
+#define DL02_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
+#define DL02_RTL_CMDS    0
+
 typedef int (*call_t)(int argc, const char* argv[]);
 
 static const char* call_args[] = { "1", "2", "3", "4" };
@@ -49,6 +54,10 @@ int dl_load_test(void)
   int    call_ret;
   int    ret;
 
+#if DL02_DEBUG_TRACE
+  rtems_rtl_trace_set_mask (DL02_DEBUG_TRACE);
+#endif
+
   o1 = dl_load_obj("/dl02-o1.o");
   if (!o1)
     return 1;
@@ -56,7 +65,7 @@ int dl_load_test(void)
   if (!o1)
     return 1;
 
-#if 0
+#if DL02_RTL_CMDS
   {
     char* list[] = { "rtl", "list", NULL };
     rtems_rtl_shell_command (2, list);
diff --git a/testsuites/libtests/dl07/dl-load.c b/testsuites/libtests/dl07/dl-load.c
new file mode 100644
index 0000000000..6e0262c7df
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-load.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#define DL07_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
+#define DL07_RTL_CMDS    0
+
+#include <dlfcn.h>
+
+#include "dl-load.h"
+
+#include <tmacros.h>
+
+#include <rtems/rtl/rtl-trace.h>
+
+typedef int (*call_sig)(void);
+
+int rtems_rtl_shell_command (int argc, char* argv[]);
+
+static void dl_load_dump (void)
+{
+#if DL07_RTL_CMDS
+  char* list[] = { "rtl", "list", NULL };
+  char* sym[] = { "rtl", "sym", NULL };
+  printf ("RTL List:\n");
+  rtems_rtl_shell_command (2, list);
+  printf ("RTL Sym:\n");
+  rtems_rtl_shell_command (2, sym);
+#endif
+}
+
+static void dl_check_resolved(void* handle, bool has_unresolved)
+{
+  int unresolved = 0;
+  rtems_test_assert (dlinfo (handle, RTLD_DI_UNRESOLVED, &unresolved) == 0);
+  if (has_unresolved)
+  {
+    if (unresolved == 0)
+    {
+      dl_load_dump();
+      rtems_test_assert (unresolved != 0);
+    }
+  }
+  else
+  {
+    if (unresolved != 0)
+    {
+      dl_load_dump();
+      rtems_test_assert (unresolved == 0);
+    }
+  }
+}
+
+static void* dl_load_obj(const char* name, bool has_unresolved)
+{
+  void* handle;
+
+  printf("load: %s\n", name);
+
+  handle = dlopen (name, RTLD_NOW | RTLD_GLOBAL);
+  if (!handle)
+  {
+    printf("dlopen failed: %s\n", dlerror());
+    return NULL;
+  }
+
+  dl_check_resolved (handle, has_unresolved);
+
+  printf ("handle: %p loaded\n", handle);
+
+  return handle;
+}
+
+static void dl_close (void* handle)
+{
+  int r;
+  printf ("handle: %p closing\n", handle);
+  r = dlclose (handle);
+  if (r != 0)
+    printf("dlclose failed: %s\n", dlerror());
+  rtems_test_assert (r == 0);
+}
+
+static int dl_call (void* handle, const char* func)
+{
+  call_sig call = dlsym (handle, func);
+  if (call == NULL)
+  {
+    printf("dlsym failed: symbol not found: %s\n", func);
+    return 1;
+  }
+  call ();
+  return 0;
+}
+
+int dl_load_test(void)
+{
+  void* o1;
+  void* o2;
+  void* o3;
+  void* o4;
+  void* o5;
+
+  printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
+
+#if DL07_DEBUG_TRACE
+  rtems_rtl_trace_set_mask (DL07_DEBUG_TRACE);
+#endif
+
+  o1 = dl_load_obj("/dl07-o1.o", false);
+  if (!o1)
+    return 1;
+  o2 = dl_load_obj("/dl07-o2.o", false);
+  if (!o1)
+    return 1;
+  o3 = dl_load_obj("/dl07-o3.o", true);
+  if (!o1)
+    return 1;
+  o4 = dl_load_obj("/dl07-o4.o", false);
+  if (!o1)
+    return 1;
+  o5 = dl_load_obj("/dl07-o5.o", false);
+  if (!o1)
+    return 1;
+
+  dl_check_resolved (o3, false);
+
+  dl_load_dump ();
+
+  printf ("\n\nRun mains in each module:\n\n");
+  if (dl_call (o1, "rtems_main_o1"))
+    return 1;
+  if (dl_call (o2, "rtems_main_o2"))
+    return 1;
+  if (dl_call (o3, "rtems_main_o3"))
+    return 1;
+  if (dl_call (o4, "rtems_main_o4"))
+    return 1;
+  if (dl_call (o5, "rtems_main_o5"))
+    return 1;
+
+  /*
+   * Try and close the dependent modules, we should get an error.
+   */
+  rtems_test_assert (dlclose (o1) != 0);
+  rtems_test_assert (dlclose (o2) != 0);
+  rtems_test_assert (dlclose (o4) != 0);
+  rtems_test_assert (dlclose (o5) != 0);
+
+  dl_close (o3);
+  rtems_test_assert (dlclose (o1) != 0);
+  dl_close (o4);
+  rtems_test_assert (dlclose (o1) != 0);
+  dl_close (o5);
+  rtems_test_assert (dlclose (o1) != 0);
+  dl_close (o2);
+  dl_close (o1);
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-load.h b/testsuites/libtests/dl07/dl-load.h
new file mode 100644
index 0000000000..72872917aa
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-load.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2014, 2018 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#include <string.h>
+
+#if !defined(_DL_LOAD_H_)
+#define _DL_LOAD_H_
+
+static inline const char* dl_localise_file (const char* file)
+{
+  return (const char*) strstr (file, "testsuites");
+}
+
+int dl_load_test(void);
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o1.c b/testsuites/libtests/dl07/dl-o1.c
new file mode 100644
index 0000000000..af5ad1bd17
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o1.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-o1.h"
+
+#include <rtems/test.h>
+#include "dl-load.h"
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+/*
+ * Create some symbols. The uninitialised will be in the common section with
+ * separated text and data and this means there is no actual section in the ELF
+ * file, the details for this are in the symbols.
+ */
+int         dl01_bss1;            /* unitialised, .bss */
+float       dl01_bss2[30];        /* unitialised, .bss */
+char        dl01_bss3[10];        /* unitialised, .bss */
+int         dl01_data1 = 1;       /* initialised, .data */
+float       dl01_data2 = 0.3333;  /* initialised, .data */
+const int   dl01_const1 = 3;      /* read-only, .const */
+const float dl01_const2 = 0.666;  /* read-only, .const */
+int dl01_func1(void)              /* code, .text */
+{
+  return 4;
+}
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o1 (void);
+
+#define DL_NAME       "dlo1"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o1 (void)
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  printf (DL_NAME ":         dl01_bss1: %4u: %p: %d\n",   PAINT_VAR (dl01_bss1));
+  printf (DL_NAME ":         dl01_bss2: %4u: %p: %f\n",   PAINT_VAR (dl01_bss2[0]));
+  printf (DL_NAME ":         dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+  printf (DL_NAME ":        dl01_data1: %4u: %p: %d\n",   PAINT_VAR (dl01_data1));
+  /* no  %f in the rtems test printer */
+  printf (DL_NAME ":        dl01_data2: %4u: %p: %f\n",   PAINT_VAR (dl01_data2));
+  printf (DL_NAME ":       dl01_const1: %4u: %p: %d\n",   PAINT_VAR (dl01_const1));
+  printf (DL_NAME ":       dl01_const2: %4u: %p: %f\n",   PAINT_VAR (dl01_const2));
+  printf (DL_NAME ":        dl01_func1: %4u: %p\n",       sizeof(dl01_func1), &dl01_func1);
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o1.h b/testsuites/libtests/dl07/dl-o1.h
new file mode 100644
index 0000000000..bf07eb6a45
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o1.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL01_H)
+#define DL01_H
+
+extern int         dl01_bss1;
+extern float       dl01_bss2[30];
+extern char        dl01_bss3[10];
+extern int         dl01_data1;
+extern float       dl01_data2;
+extern const int   dl01_const1;
+extern const float dl01_const2;
+int dl01_func1(void);
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o2.c b/testsuites/libtests/dl07/dl-o2.c
new file mode 100644
index 0000000000..423f05a16a
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o2.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o2.h"
+
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+int   dl02_bss1;
+float dl02_bss2[7];
+char  dl02_bss3[21];
+int   dl02_data1;
+float dl02_data2;
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o2 (int argc, const char* argv[]);
+
+#define DL_NAME       "dlo2"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o2 (int argc, const char* argv[])
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  printf (DL_NAME ":         dl01_bss1: %4u: %p: %d\n",   PAINT_VAR (dl01_bss1));
+  printf (DL_NAME ":         dl01_bss2: %4u: %p: %f\n",   PAINT_VAR (dl01_bss2[0]));
+  printf (DL_NAME ":         dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+  printf (DL_NAME ":        dl01_data1: %4u: %p: %d\n",   PAINT_VAR (dl01_data1));
+  /* no  %f in the rtems test printer */
+  printf (DL_NAME ":        dl01_data2: %4u: %p: %f\n",   PAINT_VAR (dl01_data2));
+  printf (DL_NAME ":       dl01_const1: %4u: %p: %d\n",   PAINT_VAR (dl01_const1));
+  printf (DL_NAME ":       dl01_const2: %4u: %p: %f\n",   PAINT_VAR (dl01_const2));
+  printf (DL_NAME ":        dl01_func1: %4u: %p\n",       sizeof(dl01_func1), &dl01_func1);
+  printf (DL_NAME ":         dl02_bss1: %4u: %p: %d\n",   PAINT_VAR (dl02_bss1));
+  printf (DL_NAME ":         dl02_bss2: %4u: %p: %f\n",   PAINT_VAR (dl02_bss2[0]));
+  printf (DL_NAME ":         dl02_bss3: %4u: %p: %02x\n", PAINT_VAR (dl02_bss3[0]));
+  printf (DL_NAME ":        dl02_data1: %4u: %p: %d\n",   PAINT_VAR (dl02_data1));
+  /* no %f in the rtems test printer */
+  printf (DL_NAME ":        dl02_data2: %4u: %p: %f\n",   PAINT_VAR (dl02_data2));
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o2.h b/testsuites/libtests/dl07/dl-o2.h
new file mode 100644
index 0000000000..0d97c5cff9
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o2.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL02_H)
+#define DL02_H
+
+/*
+ * A set of variables in dl-o2 reference by dl-03.
+ */
+
+extern int   dl02_bss1;
+extern float dl02_bss2[7];
+extern char  dl02_bss3[21];
+extern int   dl02_data1;
+extern float dl02_data2;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o3.c b/testsuites/libtests/dl07/dl-o3.c
new file mode 100644
index 0000000000..573e3df1a0
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o3.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o2.h"
+#include "dl-o4.h"
+#include "dl-o5.h"
+
+#include <inttypes.h>
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o3 (int argc, const char* argv[]);
+
+#define DL_NAME      "dlo3"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o3 (int argc, const char* argv[])
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  printf (DL_NAME ":         dl01_bss1: %4u: %p: %d\n",          PAINT_VAR (dl01_bss1));
+  printf (DL_NAME ":         dl01_bss2: %4u: %p: %f\n",          PAINT_VAR (dl01_bss2[0]));
+  printf (DL_NAME ":         dl01_bss3: %4u: %p: %02x\n",        PAINT_VAR (dl01_bss3[0]));
+  printf (DL_NAME ":        dl01_data1: %4u: %p: %d\n",          PAINT_VAR (dl01_data1));
+  /* no  %f in the rtems test printer */
+  printf (DL_NAME ":        dl01_data2: %4u: %p: %f\n",          PAINT_VAR (dl01_data2));
+  printf (DL_NAME ":       dl01_const1: %4u: %p: %d\n",          PAINT_VAR (dl01_const1));
+  printf (DL_NAME ":       dl01_const2: %4u: %p: %f\n",          PAINT_VAR (dl01_const2));
+  printf (DL_NAME ":        dl01_func1: %4u: %p\n",              sizeof(dl01_func1), &dl01_func1);
+  printf (DL_NAME ":         dl02_bss1: %4u: %p: %d\n",          PAINT_VAR (dl02_bss1));
+  printf (DL_NAME ":         dl02_bss2: %4u: %p: %f\n",          PAINT_VAR (dl02_bss2[0]));
+  printf (DL_NAME ":         dl02_bss3: %4u: %p: %02x\n",        PAINT_VAR (dl02_bss3[0]));
+  printf (DL_NAME ":        dl02_data1: %4u: %p: %d\n",          PAINT_VAR (dl02_data1));
+  /* no %f in the rtems test printer */
+  printf (DL_NAME ":        dl02_data2: %4u: %p: %f\n",          PAINT_VAR (dl02_data2));
+  printf (DL_NAME ":   dl04_unresolv_1: %4u: %p: %d\n",          PAINT_VAR (dl04_unresolv_1));
+  printf (DL_NAME ":   dl04_unresolv_2: %4u: %p: %f\n",          PAINT_VAR (dl04_unresolv_2));
+  printf (DL_NAME ":   dl04_unresolv_3: %4u: %p: %02x\n",        PAINT_VAR (dl04_unresolv_3));
+  printf (DL_NAME ":   dl04_unresolv_4: %4u: %p: %p\n",          PAINT_VAR (dl04_unresolv_4));
+  printf (DL_NAME ":   dl04_unresolv_5: %4u: %p: %d\n",          PAINT_VAR (dl04_unresolv_5));
+  printf (DL_NAME ":   dl04_unresolv_6: %4u: %p: %s\n",          PAINT_VAR (dl04_unresolv_6));
+  printf (DL_NAME ":   dl05_unresolv_1: %4u: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+  printf (DL_NAME ":   dl05_unresolv_2: %4u: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+  printf (DL_NAME ":   dl05_unresolv_3: %4u: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+  printf (DL_NAME ":   dl05_unresolv_4: %4u: %p: %" PRIu8  "\n", PAINT_VAR (dl05_unresolv_4));
+  printf (DL_NAME ":   dl05_unresolv_5: %4u: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o4.c b/testsuites/libtests/dl07/dl-o4.c
new file mode 100644
index 0000000000..a3cb1fb6c5
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o4.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o4.h"
+
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+
+int         dl04_unresolv_1;
+float       dl04_unresolv_2;
+char        dl04_unresolv_3;
+char*       dl04_unresolv_4;
+const int   dl04_unresolv_5 = 4;
+const char* dl04_unresolv_6 = "dl-O4";
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o4 (int argc, const char* argv[]);
+
+#define DL_NAME       "dlo4"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o4 (int argc, const char* argv[])
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  printf (DL_NAME ":         dl01_bss1: %4u: %p: %d\n",   PAINT_VAR (dl01_bss1));
+  printf (DL_NAME ":         dl01_bss2: %4u: %p: %f\n",   PAINT_VAR (dl01_bss2[0]));
+  printf (DL_NAME ":         dl01_bss3: %4u: %p: %02x\n", PAINT_VAR (dl01_bss3[0]));
+  printf (DL_NAME ":        dl01_data1: %4u: %p: %d\n",   PAINT_VAR (dl01_data1));
+  /* no  %f in the rtems test printer */
+  printf (DL_NAME ":        dl01_data2: %4u: %p: %f\n",   PAINT_VAR (dl01_data2));
+  printf (DL_NAME ":       dl01_const1: %4u: %p: %d\n",   PAINT_VAR (dl01_const1));
+  printf (DL_NAME ":       dl01_const2: %4u: %p: %f\n",   PAINT_VAR (dl01_const2));
+  printf (DL_NAME ":        dl01_func1: %4u: %p\n",       sizeof(dl01_func1), &dl01_func1);
+  printf (DL_NAME ":   dl04_unresolv_1: %4u: %p: %d\n",   PAINT_VAR (dl04_unresolv_1));
+  printf (DL_NAME ":   dl04_unresolv_2: %4u: %p: %f\n",   PAINT_VAR (dl04_unresolv_2));
+  printf (DL_NAME ":   dl04_unresolv_3: %4u: %p: %02x\n", PAINT_VAR (dl04_unresolv_3));
+  printf (DL_NAME ":   dl04_unresolv_4: %4u: %p: %p\n",   PAINT_VAR (dl04_unresolv_4));
+  printf (DL_NAME ":   dl04_unresolv_5: %4u: %p: %d\n",   PAINT_VAR (dl04_unresolv_5));
+  printf (DL_NAME ":   dl04_unresolv_6: %4u: %p: %s\n",   PAINT_VAR (dl04_unresolv_6));
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o4.h b/testsuites/libtests/dl07/dl-o4.h
new file mode 100644
index 0000000000..371279be9e
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o4.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#if !defined(DL04_H)
+#define DL04_H
+
+/*
+ * A set of variables in dl-o4 referenced by dl-03 and unresolved when dl-o3 is
+ * loaded. They are all uninitialised variables with various sizes in a mixed
+ * order to get various alignments. These and dl-o5 variables are designed to
+ * force the dependent tables to grow.
+ */
+
+extern int         dl04_unresolv_1;
+extern float       dl04_unresolv_2;
+extern char        dl04_unresolv_3;
+extern char*       dl04_unresolv_4;
+extern const int   dl04_unresolv_5;
+extern const char* dl04_unresolv_6;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl-o5.c b/testsuites/libtests/dl07/dl-o5.c
new file mode 100644
index 0000000000..49502b3247
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o5.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2014 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#include "dl-load.h"
+#include "dl-o1.h"
+#include "dl-o5.h"
+
+#include <inttypes.h>
+#include <rtems/test.h>
+
+#define printf(...) rtems_printf(&rtems_test_printer, __VA_ARGS__);
+
+
+uint64_t dl05_unresolv_1;
+uint16_t dl05_unresolv_2;
+uint32_t dl05_unresolv_3;
+uint8_t  dl05_unresolv_4;
+int64_t  dl05_unresolv_5;
+
+/*
+ * Yes a decl in the source. This is a modules main and I could not find which
+ * header main is defined in.
+ */
+int rtems_main_o5 (int argc, const char* argv[]);
+
+#define DL_NAME       "dlo5"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o5 (int argc, const char* argv[])
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  printf (DL_NAME ":         dl01_bss1: %4u: %p: %d\n",          PAINT_VAR (dl01_bss1));
+  printf (DL_NAME ":         dl01_bss2: %4u: %p: %f\n",          PAINT_VAR (dl01_bss2[0]));
+  printf (DL_NAME ":         dl01_bss3: %4u: %p: %02x\n",        PAINT_VAR (dl01_bss3[0]));
+  printf (DL_NAME ":        dl01_data1: %4u: %p: %d\n",          PAINT_VAR (dl01_data1));
+  /* no  %f in the rtems test printer */
+  printf (DL_NAME ":        dl01_data2: %4u: %p: %f\n",          PAINT_VAR (dl01_data2));
+  printf (DL_NAME ":       dl01_const1: %4u: %p: %d\n",          PAINT_VAR (dl01_const1));
+  printf (DL_NAME ":       dl01_const2: %4u: %p: %f\n",          PAINT_VAR (dl01_const2));
+  printf (DL_NAME ":        dl01_func1: %4u: %p\n",              sizeof(dl01_func1), &dl01_func1);
+  printf (DL_NAME ":   dl05_unresolv_1: %4u: %p: %" PRIu64 "\n", PAINT_VAR (dl05_unresolv_1));
+  printf (DL_NAME ":   dl05_unresolv_2: %4u: %p: %" PRIu16 "\n", PAINT_VAR (dl05_unresolv_2));
+  printf (DL_NAME ":   dl05_unresolv_3: %4u: %p: %" PRIu32 "\n", PAINT_VAR (dl05_unresolv_3));
+  printf (DL_NAME ":   dl05_unresolv_4: %4u: %p: %" PRIu8  "\n", PAINT_VAR (dl05_unresolv_4));
+  printf (DL_NAME ":   dl05_unresolv_5: %4u: %p: %" PRIi64 "\n", PAINT_VAR (dl05_unresolv_5));
+  return 0;
+}
diff --git a/testsuites/libtests/dl07/dl-o5.h b/testsuites/libtests/dl07/dl-o5.h
new file mode 100644
index 0000000000..04974a03d4
--- /dev/null
+++ b/testsuites/libtests/dl07/dl-o5.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#include <stdint.h>
+
+#if !defined(DL05_H)
+#define DL05_H
+
+/*
+ * A set of variables in dl-o5 referenced by dl-03 and unresolved when dl-o3 is
+ * loaded. They are all uninitialised variables with various sizes in a mixed
+ * order to get various alignments. These and dl-o4 variables are designed to
+ * force the dependent tables to grow.
+ */
+
+extern uint64_t dl05_unresolv_1;
+extern uint16_t dl05_unresolv_2;
+extern uint32_t dl05_unresolv_3;
+extern uint8_t  dl05_unresolv_4;
+extern int64_t  dl05_unresolv_5;
+
+#endif
diff --git a/testsuites/libtests/dl07/dl07.doc b/testsuites/libtests/dl07/dl07.doc
new file mode 100644
index 0000000000..9a06de16fc
--- /dev/null
+++ b/testsuites/libtests/dl07/dl07.doc
@@ -0,0 +1,27 @@
+# Copyright (c) 2018 Chris Johns <chrisj at 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.
+#
+
+This file describes the directives and concepts tested by this test set.
+
+test set name: dl07
+
+directives:
+
+  dlopen
+  dlinfo
+  dlsym
+  dlclose
+
+concepts:
+
++ Load 5 interdependent ELF object files.
++ Check there are no unreolved externals. There should be unresolved
+  externals after dl07-o3.c is loaded but resolved with o4 and o5.
++ Locate the main symbol in each lodaed object file and call.
++ Unload the ELF files in an order that checks dependent objects cannot
+  be unloaded until the references have been unloaded.
++ Repeat 100 times.
diff --git a/testsuites/libtests/dl07/dl07.scn b/testsuites/libtests/dl07/dl07.scn
new file mode 100644
index 0000000000..0c8f7891b2
--- /dev/null
+++ b/testsuites/libtests/dl07/dl07.scn
@@ -0,0 +1,510 @@
+*** BEGIN OF TEST libdl (RTL) 7 ***
+*** TEST VERSION: 5.0.0.6de8cc8ad871a197d7233a9221786d8efee87840-modified
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_NETWORKING RTEMS_POSIX_API
+*** TEST TOOLS: 7.3.0 20180125 (RTEMS 5, RSB 30da0c720b78eba16a3f5272206c07415368617b, Newlib 2ab57ad59bc35dafffa69cd4da5e228971de069f)
+--------------------------------------------------
+ Run: 0
+load: /dl07-o1.o
+handle: 0x2091160 loaded
+load: /dl07-o2.o
+handle: 0x2091ef8 loaded
+load: /dl07-o3.o
+handle: 0x2092c88 loaded
+load: /dl07-o4.o
+handle: 0x2094190 loaded
+load: /dl07-o5.o
+handle: 0x2095008 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x2091bd0: 0
+dlo1:         dl01_bss2:    4: 0x2091bd4: %f
+dlo1:         dl01_bss3:    1: 0x2091c50: 00
+dlo1:        dl01_data1:    4: 0x2091bbc: 1
+dlo1:        dl01_data2:    4: 0x2091bb8: %f
+dlo1:       dl01_const1:    4: 0x2091b98: 3
+dlo1:       dl01_const2:    4: 0x2091b94: %f
+dlo1:        dl01_func1:    1: 0x2091888
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2:         dl01_bss1:    4: 0x2091bd0: 0
+dlo2:         dl01_bss2:    4: 0x2091bd4: %f
+dlo2:         dl01_bss3:    1: 0x2091c50: 00
+dlo2:        dl01_data1:    4: 0x2091bbc: 1
+dlo2:        dl01_data2:    4: 0x2091bb8: %f
+dlo2:       dl01_const1:    4: 0x2091b98: 3
+dlo2:       dl01_const2:    4: 0x2091b94: %f
+dlo2:        dl01_func1:    1: 0x2091888
+dlo2:         dl02_bss1:    4: 0x2092928: 0
+dlo2:         dl02_bss2:    4: 0x209292c: %f
+dlo2:         dl02_bss3:    1: 0x2092948: 00
+dlo2:        dl02_data1:    4: 0x2092960: 0
+dlo2:        dl02_data2:    4: 0x2092964: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3:         dl01_bss1:    4: 0x2091bd0: 0
+dlo3:         dl01_bss2:    4: 0x2091bd4: %f
+dlo3:         dl01_bss3:    1: 0x2091c50: 00
+dlo3:        dl01_data1:    4: 0x2091bbc: 1
+dlo3:        dl01_data2:    4: 0x2091bb8: %f
+dlo3:       dl01_const1:    4: 0x2091b98: 3
+dlo3:       dl01_const2:    4: 0x2091b94: %f
+dlo3:        dl01_func1:    1: 0x2091888
+dlo3:         dl02_bss1:    4: 0x2092928: 0
+dlo3:         dl02_bss2:    4: 0x209292c: %f
+dlo3:         dl02_bss3:    1: 0x2092948: 00
+dlo3:        dl02_data1:    4: 0x2092960: 0
+dlo3:        dl02_data2:    4: 0x2092964: %f
+dlo3:   dl04_unresolv_1:    4: 0x2094d98: 0
+dlo3:   dl04_unresolv_2:    4: 0x2094d9c: %f
+dlo3:   dl04_unresolv_3:    1: 0x2094da0: 00
+dlo3:   dl04_unresolv_4:    4: 0x2094da4: 0
+dlo3:   dl04_unresolv_5:    4: 0x2094d68: 4
+dlo3:   dl04_unresolv_6:    4: 0x2094d88: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x2095a20: 0
+dlo3:   dl05_unresolv_2:    2: 0x2095a28: 0
+dlo3:   dl05_unresolv_3:    4: 0x2095a2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x2095a30: 0
+dlo3:   dl05_unresolv_5:    8: 0x2095a38: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4:         dl01_bss1:    4: 0x2091bd0: 0
+dlo4:         dl01_bss2:    4: 0x2091bd4: %f
+dlo4:         dl01_bss3:    1: 0x2091c50: 00
+dlo4:        dl01_data1:    4: 0x2091bbc: 1
+dlo4:        dl01_data2:    4: 0x2091bb8: %f
+dlo4:       dl01_const1:    4: 0x2091b98: 3
+dlo4:       dl01_const2:    4: 0x2091b94: %f
+dlo4:        dl01_func1:    1: 0x2091888
+dlo4:   dl04_unresolv_1:    4: 0x2094d98: 0
+dlo4:   dl04_unresolv_2:    4: 0x2094d9c: %f
+dlo4:   dl04_unresolv_3:    1: 0x2094da0: 00
+dlo4:   dl04_unresolv_4:    4: 0x2094da4: 0
+dlo4:   dl04_unresolv_5:    4: 0x2094d68: 4
+dlo4:   dl04_unresolv_6:    4: 0x2094d88: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5:         dl01_bss1:    4: 0x2091bd0: 0
+dlo5:         dl01_bss2:    4: 0x2091bd4: %f
+dlo5:         dl01_bss3:    1: 0x2091c50: 00
+dlo5:        dl01_data1:    4: 0x2091bbc: 1
+dlo5:        dl01_data2:    4: 0x2091bb8: %f
+dlo5:       dl01_const1:    4: 0x2091b98: 3
+dlo5:       dl01_const2:    4: 0x2091b94: %f
+dlo5:        dl01_func1:    1: 0x2091888
+dlo5:   dl05_unresolv_1:    8: 0x2095a20: 0
+dlo5:   dl05_unresolv_2:    2: 0x2095a28: 0
+dlo5:   dl05_unresolv_3:    4: 0x2095a2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x2095a30: 0
+dlo5:   dl05_unresolv_5:    8: 0x2095a38: 0
+handle: 0x2092c88 closing
+handle: 0x2094190 closing
+handle: 0x2095008 closing
+handle: 0x2091ef8 closing
+handle: 0x2091160 closing
+--------------------------------------------------
+ Run: 1
+load: /dl07-o1.o
+handle: 0x2091178 loaded
+load: /dl07-o2.o
+handle: 0x2091f40 loaded
+load: /dl07-o3.o
+handle: 0x2095010 loaded
+load: /dl07-o4.o
+handle: 0x20964e0 loaded
+load: /dl07-o5.o
+handle: 0x2097358 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x2091d00: 0
+dlo1:         dl01_bss2:    4: 0x2091d04: %f
+dlo1:         dl01_bss3:    1: 0x2091d80: 00
+dlo1:        dl01_data1:    4: 0x2091bd4: 1
+dlo1:        dl01_data2:    4: 0x2091bd0: %f
+dlo1:       dl01_const1:    4: 0x2091bb0: 3
+dlo1:       dl01_const2:    4: 0x2091bac: %f
+dlo1:        dl01_func1:    1: 0x20918a0
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2:         dl01_bss1:    4: 0x2091d00: 0
+dlo2:         dl01_bss2:    4: 0x2091d04: %f
+dlo2:         dl01_bss3:    1: 0x2091d80: 00
+dlo2:        dl01_data1:    4: 0x2091bd4: 1
+dlo2:        dl01_data2:    4: 0x2091bd0: %f
+dlo2:       dl01_const1:    4: 0x2091bb0: 3
+dlo2:       dl01_const2:    4: 0x2091bac: %f
+dlo2:        dl01_func1:    1: 0x20918a0
+dlo2:         dl02_bss1:    4: 0x2094df8: 0
+dlo2:         dl02_bss2:    4: 0x2094dfc: %f
+dlo2:         dl02_bss3:    1: 0x2094e18: 00
+dlo2:        dl02_data1:    4: 0x2094e30: 0
+dlo2:        dl02_data2:    4: 0x2094e34: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3:         dl01_bss1:    4: 0x2091d00: 0
+dlo3:         dl01_bss2:    4: 0x2091d04: %f
+dlo3:         dl01_bss3:    1: 0x2091d80: 00
+dlo3:        dl01_data1:    4: 0x2091bd4: 1
+dlo3:        dl01_data2:    4: 0x2091bd0: %f
+dlo3:       dl01_const1:    4: 0x2091bb0: 3
+dlo3:       dl01_const2:    4: 0x2091bac: %f
+dlo3:        dl01_func1:    1: 0x20918a0
+dlo3:         dl02_bss1:    4: 0x2094df8: 0
+dlo3:         dl02_bss2:    4: 0x2094dfc: %f
+dlo3:         dl02_bss3:    1: 0x2094e18: 00
+dlo3:        dl02_data1:    4: 0x2094e30: 0
+dlo3:        dl02_data2:    4: 0x2094e34: %f
+dlo3:   dl04_unresolv_1:    4: 0x20970e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x20970ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x20970f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x20970f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x20970b8: 4
+dlo3:   dl04_unresolv_6:    4: 0x20970d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x2097d70: 0
+dlo3:   dl05_unresolv_2:    2: 0x2097d78: 0
+dlo3:   dl05_unresolv_3:    4: 0x2097d7c: 0
+dlo3:   dl05_unresolv_4:    1: 0x2097d80: 0
+dlo3:   dl05_unresolv_5:    8: 0x2097d88: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4:         dl01_bss1:    4: 0x2091d00: 0
+dlo4:         dl01_bss2:    4: 0x2091d04: %f
+dlo4:         dl01_bss3:    1: 0x2091d80: 00
+dlo4:        dl01_data1:    4: 0x2091bd4: 1
+dlo4:        dl01_data2:    4: 0x2091bd0: %f
+dlo4:       dl01_const1:    4: 0x2091bb0: 3
+dlo4:       dl01_const2:    4: 0x2091bac: %f
+dlo4:        dl01_func1:    1: 0x20918a0
+dlo4:   dl04_unresolv_1:    4: 0x20970e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x20970ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x20970f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x20970f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x20970b8: 4
+dlo4:   dl04_unresolv_6:    4: 0x20970d8: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5:         dl01_bss1:    4: 0x2091d00: 0
+dlo5:         dl01_bss2:    4: 0x2091d04: %f
+dlo5:         dl01_bss3:    1: 0x2091d80: 00
+dlo5:        dl01_data1:    4: 0x2091bd4: 1
+dlo5:        dl01_data2:    4: 0x2091bd0: %f
+dlo5:       dl01_const1:    4: 0x2091bb0: 3
+dlo5:       dl01_const2:    4: 0x2091bac: %f
+dlo5:        dl01_func1:    1: 0x20918a0
+dlo5:   dl05_unresolv_1:    8: 0x2097d70: 0
+dlo5:   dl05_unresolv_2:    2: 0x2097d78: 0
+dlo5:   dl05_unresolv_3:    4: 0x2097d7c: 0
+dlo5:   dl05_unresolv_4:    1: 0x2097d80: 0
+dlo5:   dl05_unresolv_5:    8: 0x2097d88: 0
+handle: 0x2095010 closing
+handle: 0x20964e0 closing
+handle: 0x2097358 closing
+handle: 0x2091f40 closing
+handle: 0x2091178 closing
+--------------------------------------------------
+ Run: 2
+load: /dl07-o1.o
+handle: 0x2091190 loaded
+load: /dl07-o2.o
+handle: 0x2092000 loaded
+load: /dl07-o3.o
+handle: 0x20951b0 loaded
+load: /dl07-o4.o
+handle: 0x2095b40 loaded
+load: /dl07-o5.o
+handle: 0x20989a0 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x2091d00: 0
+dlo1:         dl01_bss2:    4: 0x2091d04: %f
+dlo1:         dl01_bss3:    1: 0x2091d80: 00
+dlo1:        dl01_data1:    4: 0x2091bec: 1
+dlo1:        dl01_data2:    4: 0x2091be8: %f
+dlo1:       dl01_const1:    4: 0x2091bc8: 3
+dlo1:       dl01_const2:    4: 0x2091bc4: %f
+dlo1:        dl01_func1:    1: 0x20918b8
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2:         dl01_bss1:    4: 0x2091d00: 0
+dlo2:         dl01_bss2:    4: 0x2091d04: %f
+dlo2:         dl01_bss3:    1: 0x2091d80: 00
+dlo2:        dl01_data1:    4: 0x2091bec: 1
+dlo2:        dl01_data2:    4: 0x2091be8: %f
+dlo2:       dl01_const1:    4: 0x2091bc8: 3
+dlo2:       dl01_const2:    4: 0x2091bc4: %f
+dlo2:        dl01_func1:    1: 0x20918b8
+dlo2:         dl02_bss1:    4: 0x2092738: 0
+dlo2:         dl02_bss2:    4: 0x209273c: %f
+dlo2:         dl02_bss3:    1: 0x2092758: 00
+dlo2:        dl02_data1:    4: 0x2092770: 0
+dlo2:        dl02_data2:    4: 0x2092774: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3:         dl01_bss1:    4: 0x2091d00: 0
+dlo3:         dl01_bss2:    4: 0x2091d04: %f
+dlo3:         dl01_bss3:    1: 0x2091d80: 00
+dlo3:        dl01_data1:    4: 0x2091bec: 1
+dlo3:        dl01_data2:    4: 0x2091be8: %f
+dlo3:       dl01_const1:    4: 0x2091bc8: 3
+dlo3:       dl01_const2:    4: 0x2091bc4: %f
+dlo3:        dl01_func1:    1: 0x20918b8
+dlo3:         dl02_bss1:    4: 0x2092738: 0
+dlo3:         dl02_bss2:    4: 0x209273c: %f
+dlo3:         dl02_bss3:    1: 0x2092758: 00
+dlo3:        dl02_data1:    4: 0x2092770: 0
+dlo3:        dl02_data2:    4: 0x2092774: %f
+dlo3:   dl04_unresolv_1:    4: 0x2098730: 0
+dlo3:   dl04_unresolv_2:    4: 0x2098734: %f
+dlo3:   dl04_unresolv_3:    1: 0x2098738: 00
+dlo3:   dl04_unresolv_4:    4: 0x209873c: 0
+dlo3:   dl04_unresolv_5:    4: 0x2098700: 4
+dlo3:   dl04_unresolv_6:    4: 0x2098720: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x20993b8: 0
+dlo3:   dl05_unresolv_2:    2: 0x20993c0: 0
+dlo3:   dl05_unresolv_3:    4: 0x20993c4: 0
+dlo3:   dl05_unresolv_4:    1: 0x20993c8: 0
+dlo3:   dl05_unresolv_5:    8: 0x20993d0: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4:         dl01_bss1:    4: 0x2091d00: 0
+dlo4:         dl01_bss2:    4: 0x2091d04: %f
+dlo4:         dl01_bss3:    1: 0x2091d80: 00
+dlo4:        dl01_data1:    4: 0x2091bec: 1
+dlo4:        dl01_data2:    4: 0x2091be8: %f
+dlo4:       dl01_const1:    4: 0x2091bc8: 3
+dlo4:       dl01_const2:    4: 0x2091bc4: %f
+dlo4:        dl01_func1:    1: 0x20918b8
+dlo4:   dl04_unresolv_1:    4: 0x2098730: 0
+dlo4:   dl04_unresolv_2:    4: 0x2098734: %f
+dlo4:   dl04_unresolv_3:    1: 0x2098738: 00
+dlo4:   dl04_unresolv_4:    4: 0x209873c: 0
+dlo4:   dl04_unresolv_5:    4: 0x2098700: 4
+dlo4:   dl04_unresolv_6:    4: 0x2098720: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5:         dl01_bss1:    4: 0x2091d00: 0
+dlo5:         dl01_bss2:    4: 0x2091d04: %f
+dlo5:         dl01_bss3:    1: 0x2091d80: 00
+dlo5:        dl01_data1:    4: 0x2091bec: 1
+dlo5:        dl01_data2:    4: 0x2091be8: %f
+dlo5:       dl01_const1:    4: 0x2091bc8: 3
+dlo5:       dl01_const2:    4: 0x2091bc4: %f
+dlo5:        dl01_func1:    1: 0x20918b8
+dlo5:   dl05_unresolv_1:    8: 0x20993b8: 0
+dlo5:   dl05_unresolv_2:    2: 0x20993c0: 0
+dlo5:   dl05_unresolv_3:    4: 0x20993c4: 0
+dlo5:   dl05_unresolv_4:    1: 0x20993c8: 0
+dlo5:   dl05_unresolv_5:    8: 0x20993d0: 0
+handle: 0x20951b0 closing
+handle: 0x2095b40 closing
+handle: 0x20989a0 closing
+handle: 0x2092000 closing
+handle: 0x2091190 closing
+--------------------------------------------------
+ Run: 3
+load: /dl07-o1.o
+handle: 0x20911a8 loaded
+load: /dl07-o2.o
+handle: 0x2092040 loaded
+load: /dl07-o3.o
+handle: 0x2095290 loaded
+load: /dl07-o4.o
+handle: 0x2095890 loaded
+load: /dl07-o5.o
+handle: 0x209a338 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x2091d18: 0
+dlo1:         dl01_bss2:    4: 0x2091d1c: %f
+dlo1:         dl01_bss3:    1: 0x2091d98: 00
+dlo1:        dl01_data1:    4: 0x2091d04: 1
+dlo1:        dl01_data2:    4: 0x2091d00: %f
+dlo1:       dl01_const1:    4: 0x2091be0: 3
+dlo1:       dl01_const2:    4: 0x2091bdc: %f
+dlo1:        dl01_func1:    1: 0x20918d0
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2:         dl01_bss1:    4: 0x2091d18: 0
+dlo2:         dl01_bss2:    4: 0x2091d1c: %f
+dlo2:         dl01_bss3:    1: 0x2091d98: 00
+dlo2:        dl01_data1:    4: 0x2091d04: 1
+dlo2:        dl01_data2:    4: 0x2091d00: %f
+dlo2:       dl01_const1:    4: 0x2091be0: 3
+dlo2:       dl01_const2:    4: 0x2091bdc: %f
+dlo2:        dl01_func1:    1: 0x20918d0
+dlo2:         dl02_bss1:    4: 0x2095078: 0
+dlo2:         dl02_bss2:    4: 0x209507c: %f
+dlo2:         dl02_bss3:    1: 0x2095098: 00
+dlo2:        dl02_data1:    4: 0x20950b0: 0
+dlo2:        dl02_data2:    4: 0x20950b4: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3:         dl01_bss1:    4: 0x2091d18: 0
+dlo3:         dl01_bss2:    4: 0x2091d1c: %f
+dlo3:         dl01_bss3:    1: 0x2091d98: 00
+dlo3:        dl01_data1:    4: 0x2091d04: 1
+dlo3:        dl01_data2:    4: 0x2091d00: %f
+dlo3:       dl01_const1:    4: 0x2091be0: 3
+dlo3:       dl01_const2:    4: 0x2091bdc: %f
+dlo3:        dl01_func1:    1: 0x20918d0
+dlo3:         dl02_bss1:    4: 0x2095078: 0
+dlo3:         dl02_bss2:    4: 0x209507c: %f
+dlo3:         dl02_bss3:    1: 0x2095098: 00
+dlo3:        dl02_data1:    4: 0x20950b0: 0
+dlo3:        dl02_data2:    4: 0x20950b4: %f
+dlo3:   dl04_unresolv_1:    4: 0x209a0c8: 0
+dlo3:   dl04_unresolv_2:    4: 0x209a0cc: %f
+dlo3:   dl04_unresolv_3:    1: 0x209a0d0: 00
+dlo3:   dl04_unresolv_4:    4: 0x209a0d4: 0
+dlo3:   dl04_unresolv_5:    4: 0x209a098: 4
+dlo3:   dl04_unresolv_6:    4: 0x209a0b8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x209ad50: 0
+dlo3:   dl05_unresolv_2:    2: 0x209ad58: 0
+dlo3:   dl05_unresolv_3:    4: 0x209ad5c: 0
+dlo3:   dl05_unresolv_4:    1: 0x209ad60: 0
+dlo3:   dl05_unresolv_5:    8: 0x209ad68: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4:         dl01_bss1:    4: 0x2091d18: 0
+dlo4:         dl01_bss2:    4: 0x2091d1c: %f
+dlo4:         dl01_bss3:    1: 0x2091d98: 00
+dlo4:        dl01_data1:    4: 0x2091d04: 1
+dlo4:        dl01_data2:    4: 0x2091d00: %f
+dlo4:       dl01_const1:    4: 0x2091be0: 3
+dlo4:       dl01_const2:    4: 0x2091bdc: %f
+dlo4:        dl01_func1:    1: 0x20918d0
+dlo4:   dl04_unresolv_1:    4: 0x209a0c8: 0
+dlo4:   dl04_unresolv_2:    4: 0x209a0cc: %f
+dlo4:   dl04_unresolv_3:    1: 0x209a0d0: 00
+dlo4:   dl04_unresolv_4:    4: 0x209a0d4: 0
+dlo4:   dl04_unresolv_5:    4: 0x209a098: 4
+dlo4:   dl04_unresolv_6:    4: 0x209a0b8: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5:         dl01_bss1:    4: 0x2091d18: 0
+dlo5:         dl01_bss2:    4: 0x2091d1c: %f
+dlo5:         dl01_bss3:    1: 0x2091d98: 00
+dlo5:        dl01_data1:    4: 0x2091d04: 1
+dlo5:        dl01_data2:    4: 0x2091d00: %f
+dlo5:       dl01_const1:    4: 0x2091be0: 3
+dlo5:       dl01_const2:    4: 0x2091bdc: %f
+dlo5:        dl01_func1:    1: 0x20918d0
+dlo5:   dl05_unresolv_1:    8: 0x209ad50: 0
+dlo5:   dl05_unresolv_2:    2: 0x209ad58: 0
+dlo5:   dl05_unresolv_3:    4: 0x209ad5c: 0
+dlo5:   dl05_unresolv_4:    1: 0x209ad60: 0
+dlo5:   dl05_unresolv_5:    8: 0x209ad68: 0
+handle: 0x2095290 closing
+handle: 0x2095890 closing
+handle: 0x209a338 closing
+handle: 0x2092040 closing
+handle: 0x20911a8 closing
+--------------------------------------------------
+
+  REPEAT 100 TIMES
+
+--------------------------------------------------
+ Run: 99
+load: /dl07-o1.o
+handle: 0x211fbc0 loaded
+load: /dl07-o2.o
+handle: 0x212ed58 loaded
+load: /dl07-o3.o
+handle: 0x214d6d0 loaded
+load: /dl07-o4.o
+handle: 0x214eba0 loaded
+load: /dl07-o5.o
+handle: 0x214fa18 loaded
+
+
+Run mains in each module:
+
+dlo1: module: testsuites/libtests/dl07/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x2136578: 0
+dlo1:         dl01_bss2:    4: 0x213657c: %f
+dlo1:         dl01_bss3:    1: 0x21365f8: 00
+dlo1:        dl01_data1:    4: 0x2136564: 1
+dlo1:        dl01_data2:    4: 0x2136560: %f
+dlo1:       dl01_const1:    4: 0x213fa18: 3
+dlo1:       dl01_const2:    4: 0x213fa14: %f
+dlo1:        dl01_func1:    1: 0x213f560
+dlo2: module: testsuites/libtests/dl07/dl-o2.c
+dlo2:         dl01_bss1:    4: 0x2136578: 0
+dlo2:         dl01_bss2:    4: 0x213657c: %f
+dlo2:         dl01_bss3:    1: 0x21365f8: 00
+dlo2:        dl01_data1:    4: 0x2136564: 1
+dlo2:        dl01_data2:    4: 0x2136560: %f
+dlo2:       dl01_const1:    4: 0x213fa18: 3
+dlo2:       dl01_const2:    4: 0x213fa14: %f
+dlo2:        dl01_func1:    1: 0x213f560
+dlo2:         dl02_bss1:    4: 0x214d460: 0
+dlo2:         dl02_bss2:    4: 0x214d464: %f
+dlo2:         dl02_bss3:    1: 0x214d480: 00
+dlo2:        dl02_data1:    4: 0x214d498: 0
+dlo2:        dl02_data2:    4: 0x214d49c: %f
+dlo3: module: testsuites/libtests/dl07/dl-o3.c
+dlo3:         dl01_bss1:    4: 0x2136578: 0
+dlo3:         dl01_bss2:    4: 0x213657c: %f
+dlo3:         dl01_bss3:    1: 0x21365f8: 00
+dlo3:        dl01_data1:    4: 0x2136564: 1
+dlo3:        dl01_data2:    4: 0x2136560: %f
+dlo3:       dl01_const1:    4: 0x213fa18: 3
+dlo3:       dl01_const2:    4: 0x213fa14: %f
+dlo3:        dl01_func1:    1: 0x213f560
+dlo3:         dl02_bss1:    4: 0x214d460: 0
+dlo3:         dl02_bss2:    4: 0x214d464: %f
+dlo3:         dl02_bss3:    1: 0x214d480: 00
+dlo3:        dl02_data1:    4: 0x214d498: 0
+dlo3:        dl02_data2:    4: 0x214d49c: %f
+dlo3:   dl04_unresolv_1:    4: 0x214f7a8: 0
+dlo3:   dl04_unresolv_2:    4: 0x214f7ac: %f
+dlo3:   dl04_unresolv_3:    1: 0x214f7b0: 00
+dlo3:   dl04_unresolv_4:    4: 0x214f7b4: 0
+dlo3:   dl04_unresolv_5:    4: 0x214f778: 4
+dlo3:   dl04_unresolv_6:    4: 0x214f798: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x2150430: 0
+dlo3:   dl05_unresolv_2:    2: 0x2150438: 0
+dlo3:   dl05_unresolv_3:    4: 0x215043c: 0
+dlo3:   dl05_unresolv_4:    1: 0x2150440: 0
+dlo3:   dl05_unresolv_5:    8: 0x2150448: 0
+dlo4: module: testsuites/libtests/dl07/dl-o4.c
+dlo4:         dl01_bss1:    4: 0x2136578: 0
+dlo4:         dl01_bss2:    4: 0x213657c: %f
+dlo4:         dl01_bss3:    1: 0x21365f8: 00
+dlo4:        dl01_data1:    4: 0x2136564: 1
+dlo4:        dl01_data2:    4: 0x2136560: %f
+dlo4:       dl01_const1:    4: 0x213fa18: 3
+dlo4:       dl01_const2:    4: 0x213fa14: %f
+dlo4:        dl01_func1:    1: 0x213f560
+dlo4:   dl04_unresolv_1:    4: 0x214f7a8: 0
+dlo4:   dl04_unresolv_2:    4: 0x214f7ac: %f
+dlo4:   dl04_unresolv_3:    1: 0x214f7b0: 00
+dlo4:   dl04_unresolv_4:    4: 0x214f7b4: 0
+dlo4:   dl04_unresolv_5:    4: 0x214f778: 4
+dlo4:   dl04_unresolv_6:    4: 0x214f798: dl-O4
+dlo5: module: testsuites/libtests/dl07/dl-o5.c
+dlo5:         dl01_bss1:    4: 0x2136578: 0
+dlo5:         dl01_bss2:    4: 0x213657c: %f
+dlo5:         dl01_bss3:    1: 0x21365f8: 00
+dlo5:        dl01_data1:    4: 0x2136564: 1
+dlo5:        dl01_data2:    4: 0x2136560: %f
+dlo5:       dl01_const1:    4: 0x213fa18: 3
+dlo5:       dl01_const2:    4: 0x213fa14: %f
+dlo5:        dl01_func1:    1: 0x213f560
+dlo5:   dl05_unresolv_1:    8: 0x2150430: 0
+dlo5:   dl05_unresolv_2:    2: 0x2150438: 0
+dlo5:   dl05_unresolv_3:    4: 0x215043c: 0
+dlo5:   dl05_unresolv_4:    1: 0x2150440: 0
+dlo5:   dl05_unresolv_5:    8: 0x2150448: 0
+handle: 0x214d6d0 closing
+handle: 0x214eba0 closing
+handle: 0x214fa18 closing
+handle: 0x212ed58 closing
+handle: 0x211fbc0 closing
+
+*** END OF TEST libdl (RTL) 7 ***
+
+
+*** FATAL ***
+fatal source: 5 (RTEMS_FATAL_SOURCE_EXIT)
+fatal code: 0 (0x00000000)
+RTEMS version: 5.0.0.6de8cc8ad871a197d7233a9221786d8efee87840-modified
+RTEMS tools: 7.3.0 20180125 (RTEMS 5, RSB 30da0c720b78eba16a3f5272206c07415368617b, Newlib 2ab57ad59bc35dafffa69cd4da5e228971de069f)
+executing thread ID: 0x08a010001
+executing thread name: UI1
diff --git a/testsuites/libtests/dl07/init.c b/testsuites/libtests/dl07/init.c
new file mode 100644
index 0000000000..7c482c4944
--- /dev/null
+++ b/testsuites/libtests/dl07/init.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018 Chris Johns <chrisj at rtems.org>.  All rights reserved.
+ *
+ * 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+#include "tmacros.h"
+
+#include <errno.h>
+#include <string.h>
+#include <stdint.h>
+#include <unistd.h>
+
+#include <rtems/rtl/rtl.h>
+#include <rtems/untar.h>
+
+#include "dl-load.h"
+
+const char rtems_test_name[] = "libdl (RTL) 7";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+#include "dl07-tar.h"
+
+#define TARFILE_START dl07_tar
+#define TARFILE_SIZE  dl07_tar_size
+
+static int test(void)
+{
+  int ret;
+  ret = dl_load_test();
+  if (ret)
+    rtems_test_exit(ret);
+  return 0;
+}
+
+static void Init(rtems_task_argument arg)
+{
+  int te;
+  int i;
+
+  TEST_BEGIN();
+
+  te = Untar_FromMemory((void *)TARFILE_START, (size_t)TARFILE_SIZE);
+  if (te != 0)
+  {
+    printf("untar failed: %d\n", te);
+    rtems_test_exit(1);
+    exit (1);
+  }
+
+  for (i = 0; i < 100; ++i)
+  {
+    printf ("--------------------------------------------------\n");
+    printf (" Run: %d\n", i);
+    test();
+  }
+
+  TEST_END();
+
+  rtems_test_exit(0);
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+
+#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT_TASK_STACK_SIZE (8U * 1024U)
+
+#define CONFIGURE_INIT_TASK_ATTRIBUTES   (RTEMS_DEFAULT_ATTRIBUTES | RTEMS_FLOATING_POINT)
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
-- 
2.14.1




More information about the devel mailing list