[PATCH 09/11] libdl: Add support for trampolines

chrisj at rtems.org chrisj at rtems.org
Tue Feb 5 01:43:02 UTC 2019


From: Chris Johns <chrisj at rtems.org>

- Trampolines or fixups for veneers provide long jump support
  for instruciton sets that implement short relative address
  branches. The linker provides trampolines when creating a
  static image. This patch adds trampoline support to libdl
  and the ARM architecture.

- The dl09 test requires enough memory so modules are outside
  the relative branch instruction ranges for the architecture.

Updates #3685
---
 cpukit/include/rtems/rtl/rtl-obj.h |  38 ++-
 cpukit/libdl/rtl-elf.c             |  57 ++++-
 cpukit/libdl/rtl-elf.h             |  64 ++++-
 cpukit/libdl/rtl-mdreloc-arm.c     | 301 +++++++++++++++-------
 cpukit/libdl/rtl-mdreloc-bfin.c    |  54 +++-
 cpukit/libdl/rtl-mdreloc-h8300.c   |  54 +++-
 cpukit/libdl/rtl-mdreloc-i386.c    |  54 +++-
 cpukit/libdl/rtl-mdreloc-lm32.c    |  54 +++-
 cpukit/libdl/rtl-mdreloc-m68k.c    |  54 +++-
 cpukit/libdl/rtl-mdreloc-mips.c    |  70 +++++-
 cpukit/libdl/rtl-mdreloc-moxie.c   |  54 +++-
 cpukit/libdl/rtl-mdreloc-powerpc.c |  56 ++++-
 cpukit/libdl/rtl-mdreloc-sparc.c   |  54 +++-
 cpukit/libdl/rtl-mdreloc-v850.c    |  54 +++-
 cpukit/libdl/rtl-obj.c             |  33 ++-
 testsuites/libtests/Makefile.am    |  48 +++-
 testsuites/libtests/configure.ac   |   1 +
 testsuites/libtests/dl01/dl-load.c |  41 ++-
 testsuites/libtests/dl08/dl-load.c |  36 +--
 testsuites/libtests/dl09/dl-load.c | 195 +++++++++++++++
 testsuites/libtests/dl09/dl-load.h |  21 ++
 testsuites/libtests/dl09/dl-o1.c   |  61 +++++
 testsuites/libtests/dl09/dl-o1.h   |  23 ++
 testsuites/libtests/dl09/dl-o2.c   |  39 +++
 testsuites/libtests/dl09/dl-o2.h   |  25 ++
 testsuites/libtests/dl09/dl-o3.c   |  40 +++
 testsuites/libtests/dl09/dl-o3.h   |  15 ++
 testsuites/libtests/dl09/dl-o4.c   |  40 +++
 testsuites/libtests/dl09/dl-o4.h   |  29 +++
 testsuites/libtests/dl09/dl-o5.c   |  36 +++
 testsuites/libtests/dl09/dl-o5.h   |  30 +++
 testsuites/libtests/dl09/dl09.doc  |  23 ++
 testsuites/libtests/dl09/dl09.scn  | 390 +++++++++++++++++++++++++++++
 testsuites/libtests/dl09/init.c    |  90 +++++++
 34 files changed, 2088 insertions(+), 146 deletions(-)
 create mode 100644 testsuites/libtests/dl09/dl-load.c
 create mode 100644 testsuites/libtests/dl09/dl-load.h
 create mode 100644 testsuites/libtests/dl09/dl-o1.c
 create mode 100644 testsuites/libtests/dl09/dl-o1.h
 create mode 100644 testsuites/libtests/dl09/dl-o2.c
 create mode 100644 testsuites/libtests/dl09/dl-o2.h
 create mode 100644 testsuites/libtests/dl09/dl-o3.c
 create mode 100644 testsuites/libtests/dl09/dl-o3.h
 create mode 100644 testsuites/libtests/dl09/dl-o4.c
 create mode 100644 testsuites/libtests/dl09/dl-o4.h
 create mode 100644 testsuites/libtests/dl09/dl-o5.c
 create mode 100644 testsuites/libtests/dl09/dl-o5.h
 create mode 100644 testsuites/libtests/dl09/dl09.doc
 create mode 100644 testsuites/libtests/dl09/dl09.scn
 create mode 100644 testsuites/libtests/dl09/init.c

diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index b7522a7d39..4ce356015c 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -1,5 +1,5 @@
 /*
- *  COPYRIGHT (c) 2012 Chris Johns <chrisj at rtems.org>
+ *  COPYRIGHT (c) 2012,2019 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
@@ -220,6 +220,12 @@ struct rtems_rtl_obj
   uint32_t*           sec_num;      /**< The sec nums of each obj. */
   uint32_t            obj_num;      /**< The count of elf files in an rtl
                                      *   obj. */
+  void*               trampoline;   /**< Trampoline memory. Used for fixups or
+                                     *   veneers */
+  size_t              tramp_size;   /**< Size of the tramopline memory. */
+  void*               tramp_brk;    /**< Trampoline memory allocator. MD
+                                     *   relocators can take memory from the
+                                     *   break upto the size. */
   struct link_map*    linkmap;      /**< For GDB. */
   void*               loader;       /**< The file details specific to a
                                      *   loader. */
@@ -352,6 +358,20 @@ static inline bool rtems_rtl_obj_has_symbol (const rtems_rtl_obj*     obj,
           sym < (obj->global_table + obj->global_syms));
 }
 
+/**
+ * Is there space in the trampoline memory for a trapoline.
+ *
+ * @param obj The object file's descriptor to check for available space.
+ * @param size The size to be allocated.
+ * @retval bool Returns @true if the space is available.
+ */
+static inline bool rtems_rtl_obj_has_ramp_space (const rtems_rtl_obj* obj,
+                                                 const size_t         size)
+{
+  return (obj->trampoline != NULL &&
+          ((obj->tramp_brk - obj->trampoline) + size) <= obj->tramp_size);
+}
+
 /**
  * Allocate an object structure on the heap.
  *
@@ -476,6 +496,22 @@ 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 trampoline fixup calls.
+ *
+ * @param obj The object file's descriptor.
+ * @retval true The table was allocated.
+ * @retval false The alloction failed.
+ */
+bool rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj);
+
+/**
+ * Erase the object file descriptor's trampoline table..
+ *
+ * @param obj The object file's descriptor.
+ */
+void rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj);
+
 /**
  * Allocate a table for dependent objects.
  *
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 63242acaae..96af16cb52 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -87,10 +87,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
      */
     *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;
     return true;
@@ -100,10 +97,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
 
   sect = rtems_rtl_obj_find_section_by_index (obj, sym->st_shndx);
   if (!sect)
-  {
-    rtems_rtl_set_error (EINVAL, "reloc symbol's section not found");
     return false;
-  }
 
   *value = sym->st_value + (Elf_Addr) sect->base;
   return true;
@@ -145,6 +139,35 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
                             void*               data)
 {
   rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
+
+  /*
+   * Check the reloc record to see if a trampoline is needed.
+   */
+  if (is_rela)
+  {
+    const Elf_Rela* rela = (const Elf_Rela*) relbuf;
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: rela tramp: 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_tramp (obj, rela, targetsect,
+                                            symname, sym->st_info, symvalue))
+      return false;
+  }
+  else
+  {
+    const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: rel tramp: 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_tramp (obj, rel, targetsect,
+                                           symname, sym->st_info, symvalue))
+      return false;
+  }
+
   /*
    * 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.
@@ -153,7 +176,7 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
   {
     ++rd->unresolved;
   }
-  else if (resolved && symname != NULL)
+  else if (symname != NULL)
   {
     /*
      * Find the symbol's object file. It cannot be NULL so ignore that result
@@ -556,6 +579,19 @@ rtems_rtl_elf_common (rtems_rtl_obj*      obj,
   return true;
 }
 
+static bool
+rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
+{
+  /*
+   * Add on enough space to handle the unresolved externals that need to be
+   * resolved at some point in time. They could all require fixups and
+   * trampolines.
+   */
+  obj->tramp_size +=
+    rtems_rtl_elf_relocate_tramp_max_size () * unresolved;
+  return rtems_rtl_obj_alloc_trampoline (obj);
+}
+
 static bool
 rtems_rtl_elf_dependents (rtems_rtl_obj* obj, rtems_rtl_elf_reloc_data* reloc)
 {
@@ -1297,12 +1333,19 @@ 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;
 
+  /*
+   * Parse the relocation records. It lets us know how many dependents
+   * and fixup trampolines there are.
+   */
   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_elf_alloc_trampoline (obj, relocs.unresolved))
+    return false;
+
   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
     return false;
 
diff --git a/cpukit/libdl/rtl-elf.h b/cpukit/libdl/rtl-elf.h
index 1f5f82eb89..d781bfb3a4 100644
--- a/cpukit/libdl/rtl-elf.h
+++ b/cpukit/libdl/rtl-elf.h
@@ -51,6 +51,16 @@ extern "C" {
  ** Imported NetBSD ELF Specifics End.
  **/
 
+/**
+ * Relocation trampoline relocation data.
+ */
+typedef struct rtems_rtl_mdreloc_trmap
+{
+  bool   parsing;     /**< The reloc records are being parsed. */
+  void*  tampolines;  /**< The trampoline memory. */
+  size_t size;        /**< The trampoline size. */
+} rtems_rtl_mdreloc_tramp;
+
 /**
  * Maximum string length. This a read buffering limit rather than a
  * specific ELF length. I hope this is ok as I am concerned about
@@ -80,6 +90,56 @@ uint32_t rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
  */
 bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
 
+/**
+ * Architecture specific relocation maximum trampoline size. A trampoline entry
+ * of this size is allocated for each unresolved external.
+ *
+ * @return size_t The maximum size of a trampoline for this architecture.
+ */
+size_t rtems_rtl_elf_relocate_tramp_max_size (void);
+
+/**
+ * Architecture specific relocation trampoline handler compiled in for a
+ * specific architecture by the build system. The handler determines if the
+ * relocation record requires a trampoline.
+ *
+ * @param obj The object file being relocated.
+ * @param rel The ELF relocation record.
+ * @param sect The section of the object file the relocation is for.
+ * @param symname The symbol's name.
+ * @param syminfo The ELF symbol info field.
+ * @param symvalue If a symbol is referenced, this is the symbols value.
+ * @retval bool The relocation is valid.
+ * @retval bool The relocation is not valid.
+ */
+bool rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                       const Elf_Rel*            rel,
+                                       const rtems_rtl_obj_sect* sect,
+                                       const char*               symname,
+                                       const Elf_Byte            syminfo,
+                                       const Elf_Word            symvalue);
+
+/**
+ * Architecture specific relocation handler compiled in for a specific
+ * architecture by the build system. The handler applies the relocation
+ * to the target.
+ *
+ * @param obj The object file being relocated.
+ * @param rela The ELF addend relocation record.
+ * @param sect The section of the object file the relocation is for.
+ * @param symname The symbol's name.
+ * @param syminfo The ELF symbol info field.
+ * @param symvalue If a symbol is referenced, this is the symbols value.
+ * @retval bool The relocation is valid.
+ * @retval bool The relocation is not valid.
+ */
+bool rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                        const Elf_Rela*           rela,
+                                        const rtems_rtl_obj_sect* sect,
+                                        const char*               symname,
+                                        const Elf_Byte            syminfo,
+                                        const Elf_Word            symvalue);
+
 /**
  * Architecture specific relocation handler compiled in for a specific
  * architecture by the build system. The handler applies the relocation
@@ -94,7 +154,7 @@ bool rtems_rtl_elf_rel_resolve_sym (Elf_Word type);
  * @retval bool The relocation has been applied.
  * @retval bool The relocation could not be applied.
  */
-bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+bool rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                                  const Elf_Rel*            rel,
                                  const rtems_rtl_obj_sect* sect,
                                  const char*               symname,
@@ -115,7 +175,7 @@ bool rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
  * @retval bool The relocation has been applied.
  * @retval bool The relocation could not be applied.
  */
-bool rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+bool rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                                   const Elf_Rela*           rela,
                                   const rtems_rtl_obj_sect* sect,
                                   const char*               symname,
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index ef00701d32..a00f0f8825 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -33,18 +33,17 @@
 static inline Elf_Addr
 load_ptr(void *where)
 {
-	Elf_Addr res;
+  Elf_Addr res;
 
-	memcpy(&res, where, sizeof(res));
+  memcpy(&res, where, sizeof(res));
 
-	return (res);
+  return (res);
 }
 
 static inline void
 store_ptr(void *where, Elf_Addr val)
 {
-
-	memcpy(where, &val, sizeof(val));
+  memcpy(where, &val, sizeof(val));
 }
 
 /*
@@ -67,6 +66,33 @@ sign_extend31(Elf_Addr val)
   return 0x7fffffff & val;
 }
 
+static void*
+set_veneer(void* tramopline, Elf_Addr target)
+{
+  /*
+   * http://shell-storm.org/online/Online-Assembler-and-Disassembler/
+   *
+   *  ldr.w pc, [pc]
+   */
+  uint32_t* tramp = (uint32_t*) tramopline;
+  *tramp++ = 0xf000f8df;
+  *tramp++ = (uint32_t) target;
+  return tramp;
+}
+
+static size_t
+get_veneer_size(int type)
+{
+  (void) type;
+  return 8;
+}
+
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  return 8;
+}
+
 uint32_t
 rtems_rtl_elf_section_flags (const rtems_rtl_obj* obj,
                              const Elf_Shdr*      shdr)
@@ -84,24 +110,49 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
 }
 
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rela type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
                              const Elf_Byte            syminfo,
                              const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
   return false;
 }
 
-bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
-                            const Elf_Rel*            rel,
-                            const rtems_rtl_obj_sect* sect,
-                            const char*               symname,
-                            const Elf_Byte            syminfo,
-                            const Elf_Word            symvalue)
+static bool
+rtems_rtl_elf_relor_rel (rtems_rtl_obj*            obj,
+                         const Elf_Rel*            rel,
+                         const rtems_rtl_obj_sect* sect,
+                         const char*               symname,
+                         const Elf_Byte            syminfo,
+                         const Elf_Word            symvalue,
+                         const bool                parsing)
 {
   Elf_Addr *where;
   Elf_Addr tmp;
@@ -142,21 +193,40 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
       tmp = (Elf_Sword)tmp >> 2;
 
       if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
-        printf("CALL/JUMP24 Overflow\n");
-        return false;
-      }
+        Elf_Word tramp_addr;
+        size_t   tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
 
-      *where = (*where & 0xff000000) | (tmp & 0xffffff);
+        if (parsing) {
+          obj->tramp_size += tramp_size;
+          return true;
+        }
 
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
-                (void *)*where, where, rtems_rtl_obj_oname (obj));
+        if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+          rtems_rtl_set_error (EINVAL,
+                               "%s: CALL/JUMP24: overflow: no tramp memory",
+                               sect->name);
+          return false;
+        }
 
+        tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+        obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
+
+        tmp = tramp_addr + (addend << 2) - (Elf_Addr)where;
+        tmp = (Elf_Sword)tmp >> 2;
+      }
+
+      if (!parsing) {
+        *where = (*where & 0xff000000) | (tmp & 0xffffff);
+
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: JUMP24/PC24/CALL %p @ %p in %s\n",
+                  (void *)*where, where, rtems_rtl_obj_oname (obj));
+      }
       break;
 
     case R_TYPE(V4BX):
       /* Miscellaneous, ignore */
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+      if (!parsing && rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
         printf ("rtl: V4BX %p @ %p in %s\n",
                 (void *)*where, where, rtems_rtl_obj_oname (obj));
       }
@@ -182,72 +252,78 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
         }
       }
 
-      *where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
+      if (!parsing) {
+        *where = (insn & 0xfff0f000) | ((tmp & 0xf000) << 4) | (tmp & 0xfff);
 
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
-                (void *)*where, where, rtems_rtl_obj_oname (obj));
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: MOVT_ABS/MOVW_ABS_NC %p @ %p in %s\n",
+                  (void *)*where, where, rtems_rtl_obj_oname (obj));
+      }
       break;
 
-
     case R_TYPE(REL32):     /* word32 (S + A) | T - P */
     case R_TYPE(ABS32):     /* word32 (S + A) | T */
     case R_TYPE(GLOB_DAT):  /* word32 (S + A) | T */
     case R_TYPE(PREL31):    /* word32 (S + A) | T - P */
     case R_TYPE(TARGET1):   /* Equivalent to ABS32 */
     case R_TYPE(TARGET2):   /* Equivalent to REL32 */
-      if (__predict_true(RELOC_ALIGNED_P(where))) {
-        tmp = *where + symvalue;
-        if (isThumb(symvalue))
-          tmp |= 1;
-        if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
-            ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
-          tmp -= (Elf_Addr)where;
-        else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
-          tmp = sign_extend31(tmp - (Elf_Addr)where);
-        *where = tmp;
-      } else {
-        tmp = load_ptr(where) + symvalue;
-        if (isThumb(symvalue))
-          tmp |= 1;
-        if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
-            ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
-          tmp -= (Elf_Addr)where;
-        else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
-          tmp = sign_extend31(tmp - (Elf_Addr)where);
-        store_ptr(where, tmp);
-      }
+      if (!parsing) {
+        if (__predict_true(RELOC_ALIGNED_P(where))) {
+          tmp = *where + symvalue;
+          if (isThumb(symvalue))
+            tmp |= 1;
+          if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
+              ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
+            tmp -= (Elf_Addr)where;
+          else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
+            tmp = sign_extend31(tmp - (Elf_Addr)where);
+          if (!parsing) {
+            *where = tmp;
+          }
+        } else {
+          tmp = load_ptr(where) + symvalue;
+          if (isThumb(symvalue))
+            tmp |= 1;
+          if (ELF_R_TYPE(rel->r_info) == R_TYPE(REL32) ||
+              ELF_R_TYPE(rel->r_info) == R_TYPE(TARGET2))
+            tmp -= (Elf_Addr)where;
+          else if (ELF_R_TYPE(rel->r_info) == R_TYPE(PREL31))
+            tmp = sign_extend31(tmp - (Elf_Addr)where);
+          store_ptr(where, tmp);
+        }
 
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s\n",
-                (void *)tmp, where, rtems_rtl_obj_oname (obj));
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: REL32/ABS32/GLOB_DAT/PREL31/TARGET2 %p @ %p in %s\n",
+                  (void *)tmp, where, rtems_rtl_obj_oname (obj));
+      }
       break;
 
     case R_TYPE(THM_MOVT_ABS):
     case R_TYPE(THM_MOVW_ABS_NC):
-      upper_insn = *(uint16_t *)where;
-      lower_insn = *((uint16_t *)where + 1);
-
-      addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
-               ((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
-      addend = (addend ^ 0x8000) - 0x8000;
-
-      tmp = addend + symvalue;
-      if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
-        tmp >>= 16;
-
-      *(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
-                                     ((tmp & 0xf000) >> 12) |
-                                     ((tmp & 0x0800) >> 1));
-      *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
-                                           ((tmp & 0x0700) << 4) |
-                                           (tmp & 0x00ff));
-
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
-        printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
-                (void *)*where, where, rtems_rtl_obj_oname (obj));
+      if (!parsing) {
+        upper_insn = *(uint16_t *)where;
+        lower_insn = *((uint16_t *)where + 1);
+
+        addend = ((upper_insn & 0x000f) << 12) | ((upper_insn & 0x0400) << 1) |
+          ((lower_insn & 0x7000) >> 4) | (lower_insn & 0x00ff);
+        addend = (addend ^ 0x8000) - 0x8000;
+
+        tmp = addend + symvalue;
+        if (ELF32_R_TYPE(rel->r_info) == R_ARM_THM_MOVT_ABS)
+          tmp >>= 16;
+
+        *(uint16_t *)where = (uint16_t)((upper_insn & 0xfbf0) |
+                                        ((tmp & 0xf000) >> 12) |
+                                        ((tmp & 0x0800) >> 1));
+        *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0x8f00) |
+                                              ((tmp & 0x0700) << 4) |
+                                              (tmp & 0x00ff));
+
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)) {
+          printf ("rtl: THM_MOVT_ABS/THM_MOVW_ABS_NC %p @ %p in %s\n",
+                  (void *)*where, where, rtems_rtl_obj_oname (obj));
+        }
       }
-
       break;
 
     case R_TYPE(THM_JUMP24):
@@ -278,24 +354,44 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
       tmp = tmp - (Elf_Addr)where;
 
       if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
-        printf("THM_CALL/JUMP24 overflow\n");
-        return false;
-      }
+          Elf_Word tramp_addr;
+          size_t   tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
+
+        if (parsing) {
+          obj->tramp_size += tramp_size;
+          return true;
+        }
+
+        if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+          rtems_rtl_set_error (EINVAL,
+                               "%s: THM_CALL/JUMP24: overflow: no tramp memory",
+                               sect->name);
+          return false;
+        }
 
-      sign = (tmp >> 24) & 1;
-      *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
-                                     ((tmp >> 12) & 0x3ff));
+        tramp_addr = ((Elf_Addr) obj->tramp_brk) | (symvalue & 1);
+        obj->tramp_brk = set_veneer(obj->tramp_brk, symvalue);
 
-      *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
-                                           ((sign ^ (~(tmp >> 23) & 1)) << 13) |
-                                           ((sign ^ (~(tmp >> 22) & 1)) << 11) |
-                                           ((tmp >> 1) & 0x7ff));
 
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
-        printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
-                (void *)*where, where, rtems_rtl_obj_oname (obj));
+        tmp = tramp_addr + addend;
+        tmp = tmp - (Elf_Addr)where;
       }
 
+      if (!parsing) {
+        sign = (tmp >> 24) & 1;
+        *(uint16_t *)where = (uint16_t)((upper_insn & 0xf800) | (sign << 10) |
+                                        ((tmp >> 12) & 0x3ff));
+
+        *((uint16_t *)where + 1) = (uint16_t)((lower_insn & 0xd000)|
+                                              ((sign ^ (~(tmp >> 23) & 1)) << 13) |
+                                              ((sign ^ (~(tmp >> 22) & 1)) << 11) |
+                                              ((tmp >> 1) & 0x7ff));
+
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC)){
+          printf ("rtl: THM_CALL/JUMP24 %p @ %p in %s\n",
+                  (void *)*where, where, rtems_rtl_obj_oname (obj));
+        }
+      }
       break;
 
     case R_TYPE(THM_JUMP19):
@@ -327,6 +423,7 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
         rtems_rtl_set_error (EINVAL, "%s: Overflow %" PRIu32 " "
                              "THM_JUMP19 relocations",
                              sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+        return true;
         return false;
       }
 
@@ -358,6 +455,40 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
   return true;
 }
 
+bool
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  return rtems_rtl_elf_relor_rel (obj,
+                                  rel,
+                                  sect,
+                                  symname,
+                                  syminfo,
+                                  symvalue,
+                                  true);
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
+                            const Elf_Rel*            rel,
+                            const rtems_rtl_obj_sect* sect,
+                            const char*               symname,
+                            const Elf_Byte            syminfo,
+                            const Elf_Word            symvalue)
+{
+  return rtems_rtl_elf_relor_rel (obj,
+                                  rel,
+                                  sect,
+                                  symname,
+                                  syminfo,
+                                  symvalue,
+                                  false);
+}
+
 bool
 rtems_rtl_elf_unwind_parse (const rtems_rtl_obj* obj,
                             const char*          name,
diff --git a/cpukit/libdl/rtl-mdreloc-bfin.c b/cpukit/libdl/rtl-mdreloc-bfin.c
index e1190046a3..b4c20fac24 100644
--- a/cpukit/libdl/rtl-mdreloc-bfin.c
+++ b/cpukit/libdl/rtl-mdreloc-bfin.c
@@ -32,8 +32,34 @@ load_ptr(void *where)
 	return (res);
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -112,13 +138,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-h8300.c b/cpukit/libdl/rtl-mdreloc-h8300.c
index 54af83973f..e0cb826dc8 100644
--- a/cpukit/libdl/rtl-mdreloc-h8300.c
+++ b/cpukit/libdl/rtl-mdreloc-h8300.c
@@ -25,8 +25,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -98,13 +124,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*           obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
index f0aa61b8ee..773ef8e916 100644
--- a/cpukit/libdl/rtl-mdreloc-i386.c
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -31,20 +31,70 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rela type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rel,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
                              const Elf_Byte            syminfo,
                              const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
   return false;
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
diff --git a/cpukit/libdl/rtl-mdreloc-lm32.c b/cpukit/libdl/rtl-mdreloc-lm32.c
index ad59ec2e09..cf64ea8fb3 100644
--- a/cpukit/libdl/rtl-mdreloc-lm32.c
+++ b/cpukit/libdl/rtl-mdreloc-lm32.c
@@ -25,8 +25,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
+bool
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -117,13 +143,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-m68k.c b/cpukit/libdl/rtl-mdreloc-m68k.c
index f42899b118..1981e93d56 100644
--- a/cpukit/libdl/rtl-mdreloc-m68k.c
+++ b/cpukit/libdl/rtl-mdreloc-m68k.c
@@ -45,8 +45,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symnane,
@@ -145,13 +171,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-mips.c b/cpukit/libdl/rtl-mdreloc-mips.c
index 7ad18b382f..4860fdfe72 100644
--- a/cpukit/libdl/rtl-mdreloc-mips.c
+++ b/cpukit/libdl/rtl-mdreloc-mips.c
@@ -25,18 +25,68 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rela type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
                              const Elf_Byte            syminfo,
                              const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
   return false;
 }
 
+bool
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
 /*
  * 1. _gp_disp symbol are not considered in this file.
  * 2. There is a local/external column;
@@ -46,7 +96,7 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
  * just consider symtype here.
  */
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
@@ -183,16 +233,16 @@ rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
 
       break;
 
-		default:
-     printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
-             "contents = %p\n",
+    default:
+      printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+              "contents = %p\n",
               ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
               (void *)rel->r_offset, (void *)*where);
-     rtems_rtl_set_error (EINVAL,
-                          "%s: Unsupported relocation type %ld "
-                          "in non-PLT relocations",
-                          sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
-     return false;
+      rtems_rtl_set_error (EINVAL,
+                           "%s: Unsupported relocation type %ld "
+                           "in non-PLT relocations",
+                           sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
+      return false;
   }
 
   return true;
diff --git a/cpukit/libdl/rtl-mdreloc-moxie.c b/cpukit/libdl/rtl-mdreloc-moxie.c
index 68cbeeceb2..cc0558eaa5 100644
--- a/cpukit/libdl/rtl-mdreloc-moxie.c
+++ b/cpukit/libdl/rtl-mdreloc-moxie.c
@@ -26,8 +26,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -85,13 +111,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-powerpc.c b/cpukit/libdl/rtl-mdreloc-powerpc.c
index e59c415828..b205ed5215 100644
--- a/cpukit/libdl/rtl-mdreloc-powerpc.c
+++ b/cpukit/libdl/rtl-mdreloc-powerpc.c
@@ -36,8 +36,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
+bool
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -198,14 +224,38 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
-  printf ("rtl: rel type record not supported; please report\n");
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
 
diff --git a/cpukit/libdl/rtl-mdreloc-sparc.c b/cpukit/libdl/rtl-mdreloc-sparc.c
index c0860a3d3f..bc05392659 100644
--- a/cpukit/libdl/rtl-mdreloc-sparc.c
+++ b/cpukit/libdl/rtl-mdreloc-sparc.c
@@ -144,8 +144,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return RELOC_RESOLVE_SYMBOL (type) ? true : false;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
+bool
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -261,13 +287,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   printf ("rtl: rel type record not supported; please report\n");
   return false;
 }
diff --git a/cpukit/libdl/rtl-mdreloc-v850.c b/cpukit/libdl/rtl-mdreloc-v850.c
index cc2a1fa10e..2aca5e0270 100644
--- a/cpukit/libdl/rtl-mdreloc-v850.c
+++ b/cpukit/libdl/rtl-mdreloc-v850.c
@@ -26,8 +26,34 @@ rtems_rtl_elf_rel_resolve_sym (Elf_Word type)
   return true;
 }
 
+size_t
+rtems_rtl_elf_relocate_tramp_max_size (void)
+{
+  /*
+   * Disable by returning 0.
+   */
+  return 0;
+}
+
 bool
-rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
+                                   const Elf_Rela*           rela,
+                                   const rtems_rtl_obj_sect* sect,
+                                   const char*               symname,
+                                   const Elf_Byte            syminfo,
+                                   const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rela;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  return true;
+}
+
+bool
+rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
                              const rtems_rtl_obj_sect* sect,
                              const char*               symname,
@@ -94,13 +120,37 @@ rtems_rtl_elf_relocate_rela (const rtems_rtl_obj*      obj,
 }
 
 bool
-rtems_rtl_elf_relocate_rel (const rtems_rtl_obj*      obj,
+rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
+                                  const Elf_Rel*            rel,
+                                  const rtems_rtl_obj_sect* sect,
+                                  const char*               symname,
+                                  const Elf_Byte            syminfo,
+                                  const Elf_Word            symvalue)
+{
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
+  rtems_rtl_set_error (EINVAL, "rel type record not supported");
+  return false;
+}
+
+bool
+rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
                             const rtems_rtl_obj_sect* sect,
                             const char*               symname,
                             const Elf_Byte            syminfo,
                             const Elf_Word            symvalue)
 {
+  (void) obj;
+  (void) rel;
+  (void) sect;
+  (void) symname;
+  (void) syminfo;
+  (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
   return false;
 }
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 858713dee1..6f1f2e4916 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -118,6 +118,7 @@ rtems_rtl_obj_free (rtems_rtl_obj* obj)
   rtems_rtl_obj_erase_sections (obj);
   rtems_rtl_obj_erase_dependents (obj);
   rtems_rtl_symbol_obj_erase (obj);
+  rtems_rtl_obj_erase_trampoline (obj);
   rtems_rtl_obj_free_names (obj);
   if (obj->sec_num != NULL)
     free (obj->sec_num);
@@ -556,6 +557,26 @@ rtems_rtl_obj_find_section_by_mask (const rtems_rtl_obj* obj,
   return match.sect;
 }
 
+bool
+rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
+{
+  if (obj->tramp_size == 0)
+    return true;
+  obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
+                                         obj->tramp_size,
+                                         true);
+  if (obj->trampoline == NULL)
+    rtems_rtl_set_error (ENOMEM, "no memory for the trampoline");
+  obj->tramp_brk = obj->trampoline;
+  return obj->trampoline != NULL;
+}
+
+void
+rtems_rtl_obj_erase_trampoline (rtems_rtl_obj* obj)
+{
+  rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, obj->trampoline);
+}
+
 bool
 rtems_rtl_obj_alloc_dependents (rtems_rtl_obj* obj, size_t dependents)
 {
@@ -837,9 +858,17 @@ rtems_rtl_obj_synchronize_cache (rtems_rtl_obj* obj)
                            rtems_rtl_obj_sect_sync_handler,
                            &sync_ctx);
 
-  if (sync_ctx.end_va != sync_ctx.start_va) {
+  if (sync_ctx.end_va != sync_ctx.start_va)
+  {
+    size_t size = sync_ctx.end_va - sync_ctx.start_va;
     rtems_cache_instruction_sync_after_code_change(sync_ctx.start_va,
-                              sync_ctx.end_va - sync_ctx.start_va);
+                                                   size);
+  }
+
+  if (obj->trampoline != NULL)
+  {
+    rtems_cache_instruction_sync_after_code_change(obj->trampoline,
+                                                   obj->tramp_size);
   }
 }
 
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index a5801d3cb3..22cf613dd3 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -440,7 +440,7 @@ dl05_SOURCES = dl05/init.c dl05/dl-load.c dl05/dl-cpp.cpp dl05-tar.c \
 dl05_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl05) $(support_includes)
 dl05/init.c: dl05-tar.o
 dl05.pre: $(dl05_OBJECTS) $(dl05_DEPENDENCIES)
-	@rm -f dl05.pre
+	@rm -f dl05.pre dl05-sym.o
 	$(AM_V_CXXLD)$(LINK.cc) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
 dl05-o5.o: dl05/dl-o5.cpp
 	$(AM_V_CXX)$(CXXCOMPILE) -c -o $@ $<
@@ -484,7 +484,7 @@ dl06-pre-init.o: dl06-pre-tar.o
 	$(AM_V_CC)$(COMPILE)  $(dl06_CPPFLAGS) $(CPU_CFLAGS) $(AM_CFLAGS) \
 		-DDL06_PRE -c -o $@ $(srcdir)/dl06/init.c
 dl06.pre: dl06-pre-init.o dl06/dl06-dl-load.o dl06-pre-tar.o
-	@rm -f $@
+	@rm -f $@ dl06-sym.o
 	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+ $(LDADD)
 dl06-o1.o: dl06/dl06-o1.c Makefile
 	$(AM_V_CC)$(COMPILE) -c -o $@ $<
@@ -522,7 +522,7 @@ 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
+	@rm -f dl07.pre dl07-sym.o
 	$(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 $@ $<
@@ -562,7 +562,7 @@ dl08_SOURCES = dl08/init.c dl08/dl-load.c dl08-tar.c dl08-tar.h
 dl08_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl08) $(support_includes)
 dl08/init.c: dl08-tar.o
 dl08.pre: $(dl08_OBJECTS) $(dl08_DEPENDENCIES)
-	@rm -f dl08.pre
+	@rm -f dl08.pre dl08-syms.o
 	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
 dl08-o1.o: dl08/dl-o1.c Makefile
 	$(AM_V_CC)$(COMPILE) -c -o $@ $<
@@ -605,6 +605,46 @@ CLEANFILES += dl08.pre dl08-sym.o libdl08_1.a libdl08_2.a dl08-o1.o dl08-o2.o \
 endif
 endif
 
+if DLTESTS
+if TEST_dl09
+lib_tests += dl09
+lib_screens += dl09/dl09.scn
+lib_docs += dl09/dl09.doc
+dl09_SOURCES = dl09/init.c dl09/dl-load.c dl09-tar.c dl09-tar.h
+dl09_CPPFLAGS = $(AM_CPPFLAGS) $(TEST_FLAGS_dl09) $(support_includes)
+dl09/init.c: dl09-tar.o
+dl09.pre: $(dl09_OBJECTS) $(dl09_DEPENDENCIES)
+	@rm -f dl09.pre dl09-syms.o
+	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+dl09-o1.o: dl09/dl-o1.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09-o2.o: dl09/dl-o2.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09-o3.o: dl09/dl-o3.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09-o4.o: dl09/dl-o4.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09-o5.o: dl09/dl-o5.c Makefile
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09.tar: dl09-o1.o dl09-o2.o dl09-o3.o dl09-o4.o dl09-o5.o
+	@rm -f $@
+	$(AM_V_GEN)$(PAX) -w -f $@ $+
+dl09-tar.c: dl09.tar
+	$(AM_V_GEN)$(BIN2C) -C $< $@
+dl09-tar.h: dl09.tar
+	$(AM_V_GEN)$(BIN2C) -H $< $@
+dl09-tar.o: dl09-tar.c dl09-tar.h
+	$(AM_V_CC)$(COMPILE) -c -o $@ $<
+dl09-sym.o: dl09.pre
+	$(AM_V_GEN)rtems-syms -e -C $(CC) -c "$(CFLAGS)" -o $@ $<
+dl09$(EXEEXT):  $(dl09_OBJECTS) $(dl09_DEPENDENCIES) dl09-sym.o
+	@rm -f $@
+	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
+CLEANFILES += dl09.pre dl09-sym.o dl09-o1.o dl09-o2.o dl09-o3.o dl09-o4.o \
+		dl09-o5.o dl09.tar dl09-tar.h
+endif
+endif
+
 if TEST_dumpbuf01
 lib_tests += dumpbuf01
 lib_screens += dumpbuf01/dumpbuf01.scn
diff --git a/testsuites/libtests/configure.ac b/testsuites/libtests/configure.ac
index b32d06eb22..3bcc0ec5c4 100644
--- a/testsuites/libtests/configure.ac
+++ b/testsuites/libtests/configure.ac
@@ -133,6 +133,7 @@ RTEMS_TEST_CHECK([dl05])
 RTEMS_TEST_CHECK([dl06])
 RTEMS_TEST_CHECK([dl07])
 RTEMS_TEST_CHECK([dl08])
+RTEMS_TEST_CHECK([dl09])
 RTEMS_TEST_CHECK([dumpbuf01])
 RTEMS_TEST_CHECK([dup2])
 RTEMS_TEST_CHECK([exit01])
diff --git a/testsuites/libtests/dl01/dl-load.c b/testsuites/libtests/dl01/dl-load.c
index 5438196e67..d93550d15b 100644
--- a/testsuites/libtests/dl01/dl-load.c
+++ b/testsuites/libtests/dl01/dl-load.c
@@ -12,8 +12,41 @@
 
 #include "dl-load.h"
 
-typedef int (*call_t)(int argc, const char* argv[]);
+#include <rtems/rtl/rtl-shell.h>
+#include <rtems/rtl/rtl-trace.h>
+
+#define TEST_TRACE 0
+#if TEST_TRACE
+ #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
+                      RTEMS_RTL_TRACE_WARNING | \
+                      RTEMS_RTL_TRACE_LOAD | \
+                      RTEMS_RTL_TRACE_UNLOAD | \
+                      RTEMS_RTL_TRACE_SYMBOL | \
+                      RTEMS_RTL_TRACE_RELOC | \
+                      RTEMS_RTL_TRACE_ALLOCATOR | \
+                      RTEMS_RTL_TRACE_UNRESOLVED | \
+                      RTEMS_RTL_TRACE_ARCHIVES | \
+                      RTEMS_RTL_TRACE_DEPENDENCY)
+ #define DL_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
+ #define DL_RTL_CMDS    1
+#else
+ #define DL_DEBUG_TRACE 0
+ #define DL_RTL_CMDS    0
+#endif
+
+static void dl_load_dump (void)
+{
+#if DL_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
+}
 
+typedef int (*call_t)(int argc, const char* argv[]);
 
 static const char* call_1[] = { "Line 1", "Line 2" };
 static const char* call_2[] = { "Call 2, line 1",
@@ -28,6 +61,10 @@ int dl_load_test(void)
   int    unresolved;
   char*  message = "loaded";
 
+#if DL_DEBUG_TRACE
+  rtems_rtl_trace_set_mask (DL_DEBUG_TRACE);
+#endif
+
   printf("load: /dl01-o1.o\n");
 
   handle = dlopen ("/dl01-o1.o", RTLD_NOW | RTLD_GLOBAL);
@@ -44,6 +81,8 @@ int dl_load_test(void)
 
   printf ("handle: %p %s\n", handle, message);
 
+  dl_load_dump ();
+
   call = dlsym (handle, "rtems_main");
   if (call == NULL)
   {
diff --git a/testsuites/libtests/dl08/dl-load.c b/testsuites/libtests/dl08/dl-load.c
index 615a837b39..6f4c6f3fa4 100644
--- a/testsuites/libtests/dl08/dl-load.c
+++ b/testsuites/libtests/dl08/dl-load.c
@@ -7,18 +7,24 @@
  * http://www.rtems.org/license/LICENSE.
  */
 
-#define ARCHIVE_TRACE (RTEMS_RTL_TRACE_DETAIL | \
-                       RTEMS_RTL_TRACE_WARNING | \
-                       RTEMS_RTL_TRACE_LOAD | \
-                       RTEMS_RTL_TRACE_UNLOAD | \
-                       RTEMS_RTL_TRACE_SYMBOL | \
-                       RTEMS_RTL_TRACE_RELOC | \
-                       RTEMS_RTL_TRACE_ALLOCATOR | \
-                       RTEMS_RTL_TRACE_UNRESOLVED | \
-                       RTEMS_RTL_TRACE_ARCHIVES | \
-                       RTEMS_RTL_TRACE_DEPENDENCY)
-#define DL08_DEBUG_TRACE 0 /* RTEMS_RTL_TRACE_ALL */
-#define DL08_RTL_CMDS    0
+#define TEST_TRACE 0
+#if TEST_TRACE
+ #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
+                      RTEMS_RTL_TRACE_WARNING | \
+                      RTEMS_RTL_TRACE_LOAD | \
+                      RTEMS_RTL_TRACE_UNLOAD | \
+                      RTEMS_RTL_TRACE_SYMBOL | \
+                      RTEMS_RTL_TRACE_RELOC | \
+                      RTEMS_RTL_TRACE_ALLOCATOR | \
+                      RTEMS_RTL_TRACE_UNRESOLVED | \
+                      RTEMS_RTL_TRACE_ARCHIVES | \
+                      RTEMS_RTL_TRACE_DEPENDENCY)
+ #define DL_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
+ #define DL_RTL_CMDS    1
+#else
+ #define DL_DEBUG_TRACE 0
+ #define DL_RTL_CMDS    0
+#endif
 
 #include <dlfcn.h>
 
@@ -33,7 +39,7 @@ typedef int (*call_sig)(void);
 
 static void dl_load_dump (void)
 {
-#if DL08_RTL_CMDS
+#if DL_RTL_CMDS
   char* list[] = { "rtl", "list", NULL };
   char* sym[] = { "rtl", "sym", NULL };
   printf ("RTL List:\n");
@@ -114,8 +120,8 @@ int dl_load_test(void)
 
   printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
 
-#if DL08_DEBUG_TRACE
-  rtems_rtl_trace_set_mask (DL08_DEBUG_TRACE);
+#if DL_DEBUG_TRACE
+  rtems_rtl_trace_set_mask (DL_DEBUG_TRACE);
 #endif
 
   o1 = dl_load_obj("/dl08-o1.o", false);
diff --git a/testsuites/libtests/dl09/dl-load.c b/testsuites/libtests/dl09/dl-load.c
new file mode 100644
index 0000000000..ee0ef0a335
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-load.c
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2019 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 TEST_TRACE 0
+#if TEST_TRACE
+ #define DEBUG_TRACE (RTEMS_RTL_TRACE_DETAIL | \
+                      RTEMS_RTL_TRACE_WARNING | \
+                      RTEMS_RTL_TRACE_LOAD | \
+                      RTEMS_RTL_TRACE_UNLOAD | \
+                      RTEMS_RTL_TRACE_SYMBOL | \
+                      RTEMS_RTL_TRACE_RELOC | \
+                      RTEMS_RTL_TRACE_ALLOCATOR | \
+                      RTEMS_RTL_TRACE_UNRESOLVED | \
+                      RTEMS_RTL_TRACE_ARCHIVES | \
+                      RTEMS_RTL_TRACE_DEPENDENCY)
+ #define DL09_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
+ #define DL09_RTL_CMDS    1
+#else
+ #define DL09_DEBUG_TRACE 0
+ #define DL09_RTL_CMDS    0
+#endif
+
+#include <dlfcn.h>
+
+#include "dl-load.h"
+
+#include <tmacros.h>
+
+#include <rtems/malloc.h>
+#include <rtems/rtl/rtl-shell.h>
+#include <rtems/rtl/rtl-trace.h>
+
+extern void rtems_shell_print_heap_info(
+  const char             *c,
+  const Heap_Information *h
+);
+
+typedef struct
+{
+  void* handle;
+  void* space;
+} objects;
+
+typedef struct
+{
+  const char* name;
+  bool        has_unresolved;
+  size_t      space;
+} object_def;
+
+#define MBYTES(_m) ((_m) * 1024UL * 1024UL)
+#define NUMOF(_a)  (sizeof(_a) / sizeof(_a[0]))
+
+typedef int (*call_sig)(void);
+
+static void dl_load_dump (void)
+{
+#if DL09_RTL_CMDS
+  char* list[] = { "rtl", "list", NULL };
+  char* sym[] = { "rtl", "sym", NULL };
+  Heap_Information_block info;
+  malloc_info( &info );
+  printf ("RTL List:\n");
+  rtems_rtl_shell_command (2, list);
+  printf ("RTL Sym:\n");
+  rtems_rtl_shell_command (2, sym);
+  printf ("Malloc:\n");
+  rtems_shell_print_heap_info("free", &info.Free);
+#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);
+    }
+  }
+  printf ("handel: %p: %sunresolved externals\n",
+          handle, unresolved != 0 ? "" : "no ");
+}
+
+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;
+}
+
+static void dl_object_open (object_def* od, objects* o)
+{
+  o->handle = dl_load_obj(od->name, od->has_unresolved);
+  rtems_test_assert (o->handle != NULL);
+  if (!od->has_unresolved)
+    dl_check_resolved (o->handle, false);
+  if (od->space != 0)
+  {
+    o->space = malloc (od->space);
+    printf("space alloc: %s: %d: %p\n", od->name, od->space, o->space);
+    rtems_test_assert (o->space != NULL);
+  }
+  dl_load_dump ();
+}
+
+static void dl_object_close (objects* o)
+{
+  dl_close (o->handle);
+  printf("space dealloc: %p\n", o->space);
+  free (o->space);
+}
+
+int dl_load_test(void)
+{
+  object_def od[5] = { { "/dl09-o1.o", true,  MBYTES(32) },
+                       { "/dl09-o2.o", true,  MBYTES(32) },
+                       { "/dl09-o3.o", true,  MBYTES(32) },
+                       { "/dl09-o4.o", true,  MBYTES(32) },
+                       { "/dl09-o5.o", false, 0          } };
+  objects o[5] = { 0 };
+  size_t  i;
+
+  printf ("Test source (link in strstr): %s\n", dl_localise_file (__FILE__));
+
+#if DL09_DEBUG_TRACE
+  rtems_rtl_trace_set_mask (DL09_DEBUG_TRACE);
+#endif
+
+  for (i = 0; i < NUMOF(od); ++i)
+    dl_object_open (&od[i], &o[i]);
+
+  dl_load_dump ();
+
+  printf ("Running rtems_main_o1:\n");
+  if (dl_call (o[0].handle, "rtems_main_o1"))
+    return 1;
+
+  for (i = 0; i < NUMOF(od); ++i)
+    dl_object_close (&o[i]);
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl09/dl-load.h b/testsuites/libtests/dl09/dl-load.h
new file mode 100644
index 0000000000..72872917aa
--- /dev/null
+++ b/testsuites/libtests/dl09/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/dl09/dl-o1.c b/testsuites/libtests/dl09/dl-o1.c
new file mode 100644
index 0000000000..22b839a438
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o1.c
@@ -0,0 +1,61 @@
+/*
+ * 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"
+#include "dl-o1.h"
+#include "dl-o2.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);
+
+  rtems_main_o2 ();
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl09/dl-o1.h b/testsuites/libtests/dl09/dl-o1.h
new file mode 100644
index 0000000000..f6a10f1481
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o1.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(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/dl09/dl-o2.c b/testsuites/libtests/dl09/dl-o2.c
new file mode 100644
index 0000000000..907fe9a268
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o2.c
@@ -0,0 +1,39 @@
+/*
+ * 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-o2.h"
+#include "dl-o3.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;
+
+#define DL_NAME       "dlo2"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o2 (void)
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  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));
+
+  rtems_main_o3 ();
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl09/dl-o2.h b/testsuites/libtests/dl09/dl-o2.h
new file mode 100644
index 0000000000..d6c1820f46
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o2.h
@@ -0,0 +1,25 @@
+/*
+ * 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;
+
+int rtems_main_o2 (void);
+
+#endif
diff --git a/testsuites/libtests/dl09/dl-o3.c b/testsuites/libtests/dl09/dl-o3.c
new file mode 100644
index 0000000000..4333f34057
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o3.c
@@ -0,0 +1,40 @@
+/*
+ * 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-o3.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__);
+
+#define DL_NAME      "dlo3"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o3 ()
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  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));
+
+  rtems_main_o4 ();
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl09/dl-o3.h b/testsuites/libtests/dl09/dl-o3.h
new file mode 100644
index 0000000000..8c5d18dfb1
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o3.h
@@ -0,0 +1,15 @@
+/*
+ * 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(DL03_H)
+#define DL03_H
+
+int rtems_main_o3 (void);
+
+#endif
diff --git a/testsuites/libtests/dl09/dl-o4.c b/testsuites/libtests/dl09/dl-o4.c
new file mode 100644
index 0000000000..60ada7ac68
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o4.c
@@ -0,0 +1,40 @@
+/*
+ * 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-o4.h"
+#include "dl-o5.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";
+
+#define DL_NAME       "dlo4"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o4 (void)
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  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));
+
+  rtems_main_o5 ();
+
+  return 0;
+}
diff --git a/testsuites/libtests/dl09/dl-o4.h b/testsuites/libtests/dl09/dl-o4.h
new file mode 100644
index 0000000000..bab9fc1ae4
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o4.h
@@ -0,0 +1,29 @@
+/*
+ * 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;
+
+int rtems_main_o4 (void);
+
+#endif
diff --git a/testsuites/libtests/dl09/dl-o5.c b/testsuites/libtests/dl09/dl-o5.c
new file mode 100644
index 0000000000..84e8c84173
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o5.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2019 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-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;
+
+#define DL_NAME       "dlo5"
+#define PAINT_VAR(_v) sizeof(_v), &_v, _v
+
+int rtems_main_o5 (void)
+{
+  printf (DL_NAME ": module: %s\n", dl_localise_file (__FILE__));
+  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/dl09/dl-o5.h b/testsuites/libtests/dl09/dl-o5.h
new file mode 100644
index 0000000000..bb4ce468a2
--- /dev/null
+++ b/testsuites/libtests/dl09/dl-o5.h
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+int rtems_main_o5 (void);
+
+#endif
diff --git a/testsuites/libtests/dl09/dl09.doc b/testsuites/libtests/dl09/dl09.doc
new file mode 100644
index 0000000000..4c5d97ef2a
--- /dev/null
+++ b/testsuites/libtests/dl09/dl09.doc
@@ -0,0 +1,23 @@
+# Copyright (c) 2019 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: dl09
+
+directives:
+
+  dlopen
+  dlinfo
+  dlsym
+  dlclose
+
+concepts:
+
++ Load modules with a space between then so short address range relative
+  instructions require trampolines.
++ Repeat 100 times.
diff --git a/testsuites/libtests/dl09/dl09.scn b/testsuites/libtests/dl09/dl09.scn
new file mode 100644
index 0000000000..f4b258f25b
--- /dev/null
+++ b/testsuites/libtests/dl09/dl09.scn
@@ -0,0 +1,390 @@
+*** BEGIN OF TEST libdl (RTL) 9 ***
+*** TEST VERSION: 5.0.0.ab08681fe52cad071f3a8d554af28c8bfc53b28f-modified
+*** TEST STATE: EXPECTED-PASS
+*** TEST BUILD: RTEMS_POSIX_API
+*** TEST TOOLS: 7.4.0 20181206 (RTEMS 5, RSB 257c9267cfce362138a265764c6a799c12c6b181, Newlib dc6e94551f09d3a983afd571478d63a09d6f66fa)
+--------------------------------------------------
+ Run: 0
+Test source (link in strstr): testsuites/libtests/dl09/dl-load.c
+load: /dl09-o1.o
+handel: 0x123510: unresolved externals
+handle: 0x123510 loaded
+space alloc: /dl09-o1.o: 33554432: 0x124d10
+load: /dl09-o2.o
+handel: 0x124390: unresolved externals
+handle: 0x124390 loaded
+space alloc: /dl09-o2.o: 33554432: 0x2125978
+load: /dl09-o3.o
+handel: 0x4125980: unresolved externals
+handle: 0x4125980 loaded
+space alloc: /dl09-o3.o: 33554432: 0x41267f0
+load: /dl09-o4.o
+handel: 0x41266b0: unresolved externals
+handle: 0x41266b0 loaded
+space alloc: /dl09-o4.o: 33554432: 0x6127528
+load: /dl09-o5.o
+handel: 0x8127530: no unresolved externals
+handle: 0x8127530 loaded
+handel: 0x8127530: no unresolved externals
+Running rtems_main_o1:
+dlo1: module: testsuites/libtests/dl09/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x124088: 0
+dlo1:         dl01_bss2:    4: 0x12408c: %f
+dlo1:         dl01_bss3:    1: 0x124104: 00
+dlo1:        dl01_data1:    4: 0x124070: 1
+dlo1:        dl01_data2:    4: 0x124074: %f
+dlo1:       dl01_const1:    4: 0x124050: 3
+dlo1:       dl01_const2:    4: 0x124054: %f
+dlo1:        dl01_func1:    1: 0x123cf9
+dlo2: module: testsuites/libtests/dl09/dl-o2.c
+dlo2:         dl02_bss1:    4: 0x2125468: 0
+dlo2:         dl02_bss2:    4: 0x212546c: %f
+dlo2:         dl02_bss3:    1: 0x2125488: 00
+dlo2:        dl02_data1:    4: 0x21254a0: 0
+dlo2:        dl02_data2:    4: 0x21254a4: %f
+dlo3: module: testsuites/libtests/dl09/dl-o3.c
+dlo3:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo3:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo3:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo3:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo3:   dl05_unresolv_5:    8: 0x8127d38: 0
+dlo4: module: testsuites/libtests/dl09/dl-o4.c
+dlo4:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo4:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo5: module: testsuites/libtests/dl09/dl-o5.c
+dlo5:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo5:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo5:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo5:   dl05_unresolv_5:    8: 0x8127d38: 0
+handle: 0x123510 closing
+space dealloc: 0x124d10
+handle: 0x124390 closing
+space dealloc: 0x2125978
+handle: 0x4125980 closing
+space dealloc: 0x41267f0
+handle: 0x41266b0 closing
+space dealloc: 0x6127528
+handle: 0x8127530 closing
+space dealloc: 0
+--------------------------------------------------
+ Run: 1
+Test source (link in strstr): testsuites/libtests/dl09/dl-load.c
+load: /dl09-o1.o
+handel: 0x123510: unresolved externals
+handle: 0x123510 loaded
+space alloc: /dl09-o1.o: 33554432: 0x124d10
+load: /dl09-o2.o
+handel: 0x124390: unresolved externals
+handle: 0x124390 loaded
+space alloc: /dl09-o2.o: 33554432: 0x2125978
+load: /dl09-o3.o
+handel: 0x4125980: unresolved externals
+handle: 0x4125980 loaded
+space alloc: /dl09-o3.o: 33554432: 0x41267f0
+load: /dl09-o4.o
+handel: 0x41266b0: unresolved externals
+handle: 0x41266b0 loaded
+space alloc: /dl09-o4.o: 33554432: 0x6127528
+load: /dl09-o5.o
+handel: 0x8127530: no unresolved externals
+handle: 0x8127530 loaded
+handel: 0x8127530: no unresolved externals
+Running rtems_main_o1:
+dlo1: module: testsuites/libtests/dl09/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x124088: 0
+dlo1:         dl01_bss2:    4: 0x12408c: %f
+dlo1:         dl01_bss3:    1: 0x124104: 00
+dlo1:        dl01_data1:    4: 0x124070: 1
+dlo1:        dl01_data2:    4: 0x124074: %f
+dlo1:       dl01_const1:    4: 0x124050: 3
+dlo1:       dl01_const2:    4: 0x124054: %f
+dlo1:        dl01_func1:    1: 0x123cf9
+dlo2: module: testsuites/libtests/dl09/dl-o2.c
+dlo2:         dl02_bss1:    4: 0x2125468: 0
+dlo2:         dl02_bss2:    4: 0x212546c: %f
+dlo2:         dl02_bss3:    1: 0x2125488: 00
+dlo2:        dl02_data1:    4: 0x21254a0: 0
+dlo2:        dl02_data2:    4: 0x21254a4: %f
+dlo3: module: testsuites/libtests/dl09/dl-o3.c
+dlo3:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo3:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo3:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo3:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo3:   dl05_unresolv_5:    8: 0x8127d38: 0
+dlo4: module: testsuites/libtests/dl09/dl-o4.c
+dlo4:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo4:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo5: module: testsuites/libtests/dl09/dl-o5.c
+dlo5:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo5:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo5:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo5:   dl05_unresolv_5:    8: 0x8127d38: 0
+handle: 0x123510 closing
+space dealloc: 0x124d10
+handle: 0x124390 closing
+space dealloc: 0x2125978
+handle: 0x4125980 closing
+space dealloc: 0x41267f0
+handle: 0x41266b0 closing
+space dealloc: 0x6127528
+handle: 0x8127530 closing
+space dealloc: 0
+--------------------------------------------------
+ Run: 2
+Test source (link in strstr): testsuites/libtests/dl09/dl-load.c
+load: /dl09-o1.o
+handel: 0x123510: unresolved externals
+handle: 0x123510 loaded
+space alloc: /dl09-o1.o: 33554432: 0x124d10
+load: /dl09-o2.o
+handel: 0x124390: unresolved externals
+handle: 0x124390 loaded
+space alloc: /dl09-o2.o: 33554432: 0x2125978
+load: /dl09-o3.o
+handel: 0x4125980: unresolved externals
+handle: 0x4125980 loaded
+space alloc: /dl09-o3.o: 33554432: 0x41267f0
+load: /dl09-o4.o
+handel: 0x41266b0: unresolved externals
+handle: 0x41266b0 loaded
+space alloc: /dl09-o4.o: 33554432: 0x6127528
+load: /dl09-o5.o
+handel: 0x8127530: no unresolved externals
+handle: 0x8127530 loaded
+handel: 0x8127530: no unresolved externals
+Running rtems_main_o1:
+dlo1: module: testsuites/libtests/dl09/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x124088: 0
+dlo1:         dl01_bss2:    4: 0x12408c: %f
+dlo1:         dl01_bss3:    1: 0x124104: 00
+dlo1:        dl01_data1:    4: 0x124070: 1
+dlo1:        dl01_data2:    4: 0x124074: %f
+dlo1:       dl01_const1:    4: 0x124050: 3
+dlo1:       dl01_const2:    4: 0x124054: %f
+dlo1:        dl01_func1:    1: 0x123cf9
+dlo2: module: testsuites/libtests/dl09/dl-o2.c
+dlo2:         dl02_bss1:    4: 0x2125468: 0
+dlo2:         dl02_bss2:    4: 0x212546c: %f
+dlo2:         dl02_bss3:    1: 0x2125488: 00
+dlo2:        dl02_data1:    4: 0x21254a0: 0
+dlo2:        dl02_data2:    4: 0x21254a4: %f
+dlo3: module: testsuites/libtests/dl09/dl-o3.c
+dlo3:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo3:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo3:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo3:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo3:   dl05_unresolv_5:    8: 0x8127d38: 0
+dlo4: module: testsuites/libtests/dl09/dl-o4.c
+dlo4:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo4:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo5: module: testsuites/libtests/dl09/dl-o5.c
+dlo5:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo5:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo5:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo5:   dl05_unresolv_5:    8: 0x8127d38: 0
+handle: 0x123510 closing
+space dealloc: 0x124d10
+handle: 0x124390 closing
+space dealloc: 0x2125978
+handle: 0x4125980 closing
+space dealloc: 0x41267f0
+handle: 0x41266b0 closing
+space dealloc: 0x6127528
+handle: 0x8127530 closing
+space dealloc: 0
+--------------------------------------------------
+ Run: 3
+Test source (link in strstr): testsuites/libtests/dl09/dl-load.c
+load: /dl09-o1.o
+handel: 0x123510: unresolved externals
+handle: 0x123510 loaded
+space alloc: /dl09-o1.o: 33554432: 0x124d10
+load: /dl09-o2.o
+handel: 0x124390: unresolved externals
+handle: 0x124390 loaded
+space alloc: /dl09-o2.o: 33554432: 0x2125978
+load: /dl09-o3.o
+handel: 0x4125980: unresolved externals
+handle: 0x4125980 loaded
+space alloc: /dl09-o3.o: 33554432: 0x41267f0
+load: /dl09-o4.o
+handel: 0x41266b0: unresolved externals
+handle: 0x41266b0 loaded
+space alloc: /dl09-o4.o: 33554432: 0x6127528
+load: /dl09-o5.o
+handel: 0x8127530: no unresolved externals
+handle: 0x8127530 loaded
+handel: 0x8127530: no unresolved externals
+Running rtems_main_o1:
+dlo1: module: testsuites/libtests/dl09/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x124088: 0
+dlo1:         dl01_bss2:    4: 0x12408c: %f
+dlo1:         dl01_bss3:    1: 0x124104: 00
+dlo1:        dl01_data1:    4: 0x124070: 1
+dlo1:        dl01_data2:    4: 0x124074: %f
+dlo1:       dl01_const1:    4: 0x124050: 3
+dlo1:       dl01_const2:    4: 0x124054: %f
+dlo1:        dl01_func1:    1: 0x123cf9
+dlo2: module: testsuites/libtests/dl09/dl-o2.c
+dlo2:         dl02_bss1:    4: 0x2125468: 0
+dlo2:         dl02_bss2:    4: 0x212546c: %f
+dlo2:         dl02_bss3:    1: 0x2125488: 00
+dlo2:        dl02_data1:    4: 0x21254a0: 0
+dlo2:        dl02_data2:    4: 0x21254a4: %f
+dlo3: module: testsuites/libtests/dl09/dl-o3.c
+dlo3:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo3:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo3:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo3:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo3:   dl05_unresolv_5:    8: 0x8127d38: 0
+dlo4: module: testsuites/libtests/dl09/dl-o4.c
+dlo4:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo4:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo5: module: testsuites/libtests/dl09/dl-o5.c
+dlo5:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo5:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo5:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo5:   dl05_unresolv_5:    8: 0x8127d38: 0
+handle: 0x123510 closing
+space dealloc: 0x124d10
+handle: 0x124390 closing
+space dealloc: 0x2125978
+handle: 0x4125980 closing
+space dealloc: 0x41267f0
+handle: 0x41266b0 closing
+space dealloc: 0x6127528
+handle: 0x8127530 closing
+space dealloc: 0
+--------------------------------------------------
+
+  REPEAT 100 TIMES
+
+--------------------------------------------------
+ Run: 99
+Test source (link in strstr): testsuites/libtests/dl09/dl-load.c
+load: /dl09-o1.o
+handel: 0x123510: unresolved externals
+handle: 0x123510 loaded
+space alloc: /dl09-o1.o: 33554432: 0x124d10
+load: /dl09-o2.o
+handel: 0x124390: unresolved externals
+handle: 0x124390 loaded
+space alloc: /dl09-o2.o: 33554432: 0x2125978
+load: /dl09-o3.o
+handel: 0x4125980: unresolved externals
+handle: 0x4125980 loaded
+space alloc: /dl09-o3.o: 33554432: 0x41267f0
+load: /dl09-o4.o
+handel: 0x41266b0: unresolved externals
+handle: 0x41266b0 loaded
+space alloc: /dl09-o4.o: 33554432: 0x6127528
+load: /dl09-o5.o
+handel: 0x8127530: no unresolved externals
+handle: 0x8127530 loaded
+handel: 0x8127530: no unresolved externals
+Running rtems_main_o1:
+dlo1: module: testsuites/libtests/dl09/dl-o1.c
+dlo1:         dl01_bss1:    4: 0x124088: 0
+dlo1:         dl01_bss2:    4: 0x12408c: %f
+dlo1:         dl01_bss3:    1: 0x124104: 00
+dlo1:        dl01_data1:    4: 0x124070: 1
+dlo1:        dl01_data2:    4: 0x124074: %f
+dlo1:       dl01_const1:    4: 0x124050: 3
+dlo1:       dl01_const2:    4: 0x124054: %f
+dlo1:        dl01_func1:    1: 0x123cf9
+dlo2: module: testsuites/libtests/dl09/dl-o2.c
+dlo2:         dl02_bss1:    4: 0x2125468: 0
+dlo2:         dl02_bss2:    4: 0x212546c: %f
+dlo2:         dl02_bss3:    1: 0x2125488: 00
+dlo2:        dl02_data1:    4: 0x21254a0: 0
+dlo2:        dl02_data2:    4: 0x21254a4: %f
+dlo3: module: testsuites/libtests/dl09/dl-o3.c
+dlo3:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo3:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo3:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo3:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo3:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo3:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo3:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo3:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo3:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo3:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo3:   dl05_unresolv_5:    8: 0x8127d38: 0
+dlo4: module: testsuites/libtests/dl09/dl-o4.c
+dlo4:   dl04_unresolv_1:    4: 0x61270e8: 0
+dlo4:   dl04_unresolv_2:    4: 0x61270ec: %f
+dlo4:   dl04_unresolv_3:    1: 0x61270f0: 00
+dlo4:   dl04_unresolv_4:    4: 0x61270f4: 0
+dlo4:   dl04_unresolv_5:    4: 0x61270bc: 4
+dlo4:   dl04_unresolv_6:    4: 0x61270d8: dl-O4
+dlo5: module: testsuites/libtests/dl09/dl-o5.c
+dlo5:   dl05_unresolv_1:    8: 0x8127d20: 0
+dlo5:   dl05_unresolv_2:    2: 0x8127d28: 0
+dlo5:   dl05_unresolv_3:    4: 0x8127d2c: 0
+dlo5:   dl05_unresolv_4:    1: 0x8127d30: 0
+dlo5:   dl05_unresolv_5:    8: 0x8127d38: 0
+handle: 0x123510 closing
+space dealloc: 0x124d10
+handle: 0x124390 closing
+space dealloc: 0x2125978
+handle: 0x4125980 closing
+space dealloc: 0x41267f0
+handle: 0x41266b0 closing
+space dealloc: 0x6127528
+handle: 0x8127530 closing
+space dealloc: 0
+
+*** END OF TEST libdl (RTL) 9 ***
+
+
+*** FATAL ***
+fatal source: 5 (RTEMS_FATAL_SOURCE_EXIT)
+fatal code: 0 (0x00000000)
+RTEMS version: 5.0.0.ab08681fe52cad071f3a8d554af28c8bfc53b28f-modified
+RTEMS tools: 7.4.0 20181206 (RTEMS 5, RSB 257c9267cfce362138a265764c6a799c12c6b181, Newlib dc6e94551f09d3a983afd571478d63a09d6f66fa)
+executing thread ID: 0x08a010001
+executing thread name: UI1
diff --git a/testsuites/libtests/dl09/init.c b/testsuites/libtests/dl09/init.c
new file mode 100644
index 0000000000..dbcc7ba84c
--- /dev/null
+++ b/testsuites/libtests/dl09/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) 9";
+
+/* forward declarations to avoid warnings */
+static rtems_task Init(rtems_task_argument argument);
+
+#include "dl09-tar.h"
+
+#define TARFILE_START dl09_tar
+#define TARFILE_SIZE  dl09_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.19.1




More information about the devel mailing list