Index: cpukit/include/rtems/rtl/rtl-obj.h
===================================================================
--- cpukit/include/rtems/rtl/rtl-obj.h	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/include/rtems/rtl/rtl-obj.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -208,5 +208,5 @@
   void*               const_base;   /**< The base address of the const section
                                      *   in memory. */
-  size_t              const_size;    /**< The size of the const section. */
+  size_t              const_size;   /**< The size of the const section. */
   void*               eh_base;      /**< The base address of the eh section in
                                      *   memory. */
@@ -228,8 +228,12 @@
   void*               trampoline;   /**< Trampoline memory. Used for fixups or
                                      *   veneers */
-  size_t              tramp_size;   /**< Size of the tramopline memory. */
+  size_t              tramp_size;   /**< Size of a tramopline slot. */
+  size_t              tramps_size;  /**< Size of the trampoline memory. */
   void*               tramp_brk;    /**< Trampoline memory allocator. MD
                                      *   relocators can take memory from the
                                      *   break upto the size. */
+  size_t              tramp_relocs; /**< Number of slots reserved for
+                                     *   relocs. The remainder are for
+                                     *   unresolved symbols. */
   struct link_map*    linkmap;      /**< For GDB. */
   void*               loader;       /**< The file details specific to a
@@ -371,9 +375,33 @@
  * @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)
+static inline bool rtems_rtl_obj_has_tramp_space (const rtems_rtl_obj* obj,
+                                                  const size_t         size)
 {
   return (obj->trampoline != NULL &&
-          ((obj->tramp_brk - obj->trampoline) + size) <= obj->tramp_size);
+          ((obj->tramp_brk - obj->trampoline) + size) <= obj->tramps_size);
+}
+
+/**
+ * Trampoline slots.
+ *
+ * @param obj The object file's descriptor.
+ * @retval size_t The number of trampoline slots.
+ */
+static inline size_t rtems_rtl_obj_trampoline_slots (const rtems_rtl_obj* obj)
+{
+  return obj->trampoline == NULL || obj->tramp_size == 0 ?
+    0 : obj->tramps_size / obj->tramp_size;
+}
+
+/**
+ * Number of trampolines.
+ *
+ * @param obj The object file's descriptor.
+ * @retval size_t The number of trampolines.
+ */
+static inline size_t rtems_rtl_obj_trampolines (const rtems_rtl_obj* obj)
+{
+  return obj->trampoline == NULL || obj->tramp_size == 0 ?
+    0 : (obj->tramp_brk - obj->trampoline) / obj->tramp_size;
 }
 
Index: cpukit/include/rtems/rtl/rtl-unresolved.h
===================================================================
--- cpukit/include/rtems/rtl/rtl-unresolved.h	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/include/rtems/rtl/rtl-unresolved.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -1,4 +1,4 @@
 /*
- *  COPYRIGHT (c) 2012, 2018 Chris Johns <chrisj@rtems.org>
+ *  COPYRIGHT (c) 2012, 2019 Chris Johns <chrisj@rtems.org>
  *
  *  The license and distribution terms for this file may be
@@ -74,5 +74,6 @@
   rtems_rtl_unresolved_empty = 0,  /**< The records is empty. Must always be 0 */
   rtems_rtl_unresolved_symbol = 1, /**< The record is a symbol. */
-  rtems_rtl_unresolved_reloc = 2   /**< The record is a relocation record. */
+  rtems_rtl_unresolved_reloc = 2,  /**< The record is a relocation record. */
+  rtems_rtl_trampoline_reloc = 3   /**< The record is a trampoline relocation record. */
 } rtems_rtl_unresolved_rtype;
 
@@ -102,5 +103,5 @@
 /**
  * Unresolved externals symbols require the relocation records to be held
- * and references.
+ * and referenced.
  */
 typedef struct rtems_rtl_unresolv_reloc
@@ -114,4 +115,16 @@
 
 /**
+ * Trampolines require the relocation records to be held
+ */
+typedef struct rtems_rtl_tramp_reloc
+{
+  rtems_rtl_obj* obj;      /**< The relocation's object file. */
+  uint16_t       flags;    /**< Format specific flags. */
+  uint16_t       sect;     /**< The target section. */
+  rtems_rtl_word symvalue; /**< The symbol's value. */
+  rtems_rtl_word rel[3];   /**< Relocation record. */
+} rtems_rtl_tramp_reloc;
+
+/**
  * Unresolved externals records.
  */
@@ -122,5 +135,6 @@
   {
     rtems_rtl_unresolv_symbol name;   /**< The symbol, or */
-    rtems_rtl_unresolv_reloc  reloc;  /**< the relocation record. */
+    rtems_rtl_unresolv_reloc  reloc;  /**< The relocation record. */
+    rtems_rtl_tramp_reloc     tramp;  /**< The trampoline relocation record. */
   } rec;
 } rtems_rtl_unresolv_rec;
Index: cpukit/include/rtems/rtl/rtl.h
===================================================================
--- cpukit/include/rtems/rtl/rtl.h	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/include/rtems/rtl/rtl.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -73,5 +73,5 @@
  * The number of relocation record per block in the unresolved table.
  */
-#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (64)
+#define RTEMS_RTL_UNRESOLVED_BLOCK_SIZE (256)
 
 /**
Index: cpukit/libdl/rtl-allocator.c
===================================================================
--- cpukit/libdl/rtl-allocator.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-allocator.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -148,5 +148,5 @@
 
   if (rtems_rtl_trace (RTEMS_RTL_TRACE_ALLOCATOR))
-    printf ("rtl: alloc: wr-enable: addr=%p\n", address);
+    printf ("rtl: alloc: wr-disable: addr=%p\n", address);
 
   if (rtl != NULL && address != NULL)
Index: cpukit/libdl/rtl-elf.c
===================================================================
--- cpukit/libdl/rtl-elf.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-elf.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -1,4 +1,4 @@
 /*
- *  COPYRIGHT (c) 2012-2018 Chris Johns <chrisj@rtems.org>
+ *  COPYRIGHT (c) 2012-2019 Chris Johns <chrisj@rtems.org>
  *
  *  The license and distribution terms for this file may be
@@ -32,9 +32,10 @@
 #include "rtl-error.h"
 #include <rtems/rtl/rtl-trace.h>
+#include "rtl-trampoline.h"
 #include "rtl-unwind.h"
 #include <rtems/rtl/rtl-unresolved.h>
 
 /**
- * The offsets in the unresolved array.
+ * The offsets in the reloc words.
  */
 #define REL_R_OFFSET (0)
@@ -167,64 +168,75 @@
 {
   rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
-
-  /*
-   * The symbol has to have been resolved to parse the reloc record. Unresolved
-   * symbols are handled in the relocator but we need to count them here so a
-   * trampoline is accounted for. We have to assume the unresolved may be out of
-   * of range.
-   */
-  if (!resolved)
-  {
-    ++rd->unresolved;
+  rtems_rtl_word            rel_words[3];
+  rtems_rtl_elf_rel_status  rs;
+
+  /*
+   * 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: %c:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
+              ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
+              ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
+              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);
+    rs = rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
+                                            symname, sym->st_info, symvalue);
+    rel_words[REL_R_OFFSET] = rela->r_offset;
+    rel_words[REL_R_INFO] = rela->r_info;
+    rel_words[REL_R_ADDEND] = rela->r_addend;
   }
   else
   {
+    const Elf_Rel* rel = (const Elf_Rel*) relbuf;
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: rel tramp: sym: %c:%s(%d)=%08jx type:%d off:%08jx\n",
+              ELF_ST_BIND (sym->st_info) == STB_GLOBAL ||
+              ELF_ST_BIND (sym->st_info) == STB_WEAK ? 'G' : 'L',
+              symname, (int) ELF_R_SYM (rel->r_info),
+              (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
+              (uintmax_t) rel->r_offset);
+    rs = rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
+                                           symname, sym->st_info, symvalue);
+    rel_words[REL_R_OFFSET] = rel->r_offset;
+    rel_words[REL_R_INFO] = rel->r_info;
+    rel_words[REL_R_ADDEND] = 0;
+  }
+
+  if (rs == rtems_rtl_elf_rel_failure)
+    return false;
+
+  if (rs == rtems_rtl_elf_rel_tramp_cache || rs == rtems_rtl_elf_rel_tramp_add)
+  {
+    uint32_t flags = (is_rela ? 1 : 0) | (resolved ? 0 : 1 << 1) | (sym->st_info << 8);
+    if (!rtems_rtl_trampoline_add (obj, flags,
+                                   targetsect->section, symvalue, rel_words))
+      return false;
+  }
+
+  /*
+   * Handle any dependencies if there is a valid symbol.
+   */
+  if (symname != NULL)
+  {
     /*
-     * Check the reloc record to see if a trampoline is needed.
+     * Find the symbol's object file. It cannot be NULL so ignore that result
+     * if returned, it means something is corrupted. We are in an iterator.
      */
-    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 (symname != NULL)
+    rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
+    if (sobj != NULL)
     {
       /*
-       * Find the symbol's object file. It cannot be NULL so ignore that result
-       * if returned, it means something is corrupted. We are in an iterator.
+       * A dependency is not the base kernel image or itself. Tag the object as
+       * having been visited so we count it only once.
        */
-      rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
-      if (sobj != NULL)
-      {
-        /*
-         * A dependency is not the base kernel image or itself. Tag the object as
-         * having been visited so we count it only once.
-         */
-        if (sobj != rtems_rtl_baseimage () && obj != sobj &&
-            (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
-        {
-          sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
-          ++rd->dependents;
-        }
+      if (sobj != rtems_rtl_baseimage () && obj != sobj &&
+          (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
+      {
+        sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
+        ++rd->dependents;
       }
     }
@@ -279,5 +291,6 @@
   else
   {
-    rtems_rtl_obj* sobj;
+    rtems_rtl_obj*           sobj;
+    rtems_rtl_elf_rel_status rs;
 
     if (is_rela)
@@ -288,6 +301,7 @@
                 (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
                 (uintmax_t) rela->r_offset, (int) rela->r_addend);
-      if (!rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
-                                        symname, sym->st_info, symvalue))
+      rs = rtems_rtl_elf_relocate_rela (obj, rela, targetsect,
+                                        symname, sym->st_info, symvalue);
+      if (rs != rtems_rtl_elf_rel_no_error)
         return false;
     }
@@ -299,6 +313,7 @@
                 (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
                 (uintmax_t) rel->r_offset);
-      if (!rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
-                                       symname, sym->st_info, symvalue))
+      rs = rtems_rtl_elf_relocate_rel (obj, rel, targetsect,
+                                       symname, sym->st_info, symvalue);
+      if (rs != rtems_rtl_elf_rel_no_error)
         return false;
     }
@@ -420,5 +435,8 @@
      * Only need the name of the symbol if global or a common symbol.
      */
-    if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
+    if (ELF_ST_TYPE (sym.st_info) == STT_OBJECT ||
+        ELF_ST_TYPE (sym.st_info) == STT_COMMON ||
+        ELF_ST_TYPE (sym.st_info) == STT_FUNC ||
+        ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
         ELF_ST_TYPE (sym.st_info) == STT_TLS ||
         sym.st_shndx == SHN_COMMON)
@@ -492,8 +510,9 @@
                                    rtems_rtl_obj_sym*        sym)
 {
-  rtems_rtl_obj_sect* sect;
-  bool                is_rela;
-  Elf_Word            symvalue;
-  rtems_rtl_obj*      sobj;
+  rtems_rtl_obj_sect*      sect;
+  bool                     is_rela;
+  Elf_Word                 symvalue;
+  rtems_rtl_obj*           sobj;
+  rtems_rtl_elf_rel_status rs;
 
   is_rela = reloc->flags & 1;
@@ -517,6 +536,7 @@
                   (int) ELF_R_SYM (rela.r_info), (int) ELF_R_TYPE (rela.r_info),
                   (uintmax_t) rela.r_offset, (int) rela.r_addend);
-    if (!rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
-                                      sym->name, sym->data, symvalue))
+    rs = rtems_rtl_elf_relocate_rela (reloc->obj, &rela, sect,
+                                      sym->name, sym->data, symvalue);
+    if (rs != rtems_rtl_elf_rel_no_error)
       return false;
   }
@@ -530,6 +550,7 @@
               (int) ELF_R_SYM (rel.r_info), (int) ELF_R_TYPE (rel.r_info),
               (uintmax_t) rel.r_offset);
-    if (!rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
-                                     sym->name, sym->data, symvalue))
+    rs = rtems_rtl_elf_relocate_rel (reloc->obj, &rel, sect,
+                                     sym->name, sym->data, symvalue);
+    if (rs != rtems_rtl_elf_rel_no_error)
       return false;
   }
@@ -622,7 +643,105 @@
 }
 
+/**
+ * Struct to handle trampoline reloc recs in the unresolved table.
+ */
+typedef struct rtems_rtl_tramp_data
+{
+  bool           failure;
+  rtems_rtl_obj* obj;
+  size_t         count;
+  size_t         total;
+} rtems_rtl_tramp_data;
+
+static bool
+rtems_rtl_elf_tramp_resolve_reloc (rtems_rtl_unresolv_rec* rec,
+                                   void*                   data)
+{
+  rtems_rtl_tramp_data* td = (rtems_rtl_tramp_data*) data;
+  if (rec->type == rtems_rtl_trampoline_reloc)
+  {
+    const rtems_rtl_tramp_reloc* tramp = &rec->rec.tramp;
+
+    ++td->total;
+
+    if (tramp->obj == td->obj)
+    {
+      const rtems_rtl_obj_sect* targetsect;
+      Elf_Byte                  st_info;
+      Elf_Word                  symvalue;
+      rtems_rtl_elf_rel_status  rs;
+      bool*                     failure = (bool*) data;
+      const bool                is_rela = (tramp->flags & 1) == 1;
+      const bool                unresolved = (tramp->flags & (1 << 1)) != 0;
+
+      ++td->count;
+
+      targetsect = rtems_rtl_obj_find_section_by_index (tramp->obj, tramp->sect);
+      st_info = tramp->flags >> 8;
+      symvalue = tramp->symvalue;
+
+      if (is_rela)
+      {
+        Elf_Rela rela = {
+          .r_offset = tramp->rel[REL_R_OFFSET],
+          .r_info   = tramp->rel[REL_R_INFO],
+          .r_addend = tramp->rel[REL_R_ADDEND]
+        };
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: rela tramp: check: %c(%d)=%08jx type:%d off:%08jx addend:%d\n",
+                  ELF_ST_BIND (st_info) == STB_GLOBAL ||
+                  ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
+                  (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);
+        rs = rtems_rtl_elf_relocate_rela_tramp (tramp->obj, &rela, targetsect,
+                                                NULL, st_info, symvalue);
+      }
+      else
+      {
+        Elf_Rel rel = {
+          .r_offset = tramp->rel[REL_R_OFFSET],
+          .r_info   = tramp->rel[REL_R_INFO],
+        };
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: rel tramp: check: %c(%d)=%08jx type:%d off:%08jx\n",
+                  ELF_ST_BIND (st_info) == STB_GLOBAL ||
+                  ELF_ST_BIND (st_info) == STB_WEAK ? 'G' : 'L',
+                  (int) ELF_R_SYM (rel.r_info),
+                  (uintmax_t) symvalue, (int) ELF_R_TYPE (rel.r_info),
+                  (uintmax_t) rel.r_offset);
+        rs = rtems_rtl_elf_relocate_rel_tramp (tramp->obj, &rel, targetsect,
+                                               NULL, st_info, symvalue);
+      }
+
+      if (unresolved || rs == rtems_rtl_elf_rel_tramp_add)
+        tramp->obj->tramps_size += tramp->obj->tramp_size;
+      if (rs == rtems_rtl_elf_rel_failure)
+      {
+        *failure = true;
+        return true;
+      }
+    }
+  }
+
+  return false;
+}
+
 static bool
 rtems_rtl_elf_alloc_trampoline (rtems_rtl_obj* obj, size_t unresolved)
 {
+  rtems_rtl_tramp_data td =  { 0 };
+  td.obj = obj;
+  /*
+   * See which relocs are out of range and need a trampoline.
+   */
+  rtems_rtl_unresolved_iterate (rtems_rtl_elf_tramp_resolve_reloc, &td);
+  if (td.failure)
+    return false;
+  rtems_rtl_trampoline_remove (obj);
+  obj->tramp_relocs = obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size;
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+    printf ("rtl: tramp:elf: tramps: %zu count:%zu total:%zu\n",
+            obj->tramp_relocs, td.count, td.total);
   /*
    * Add on enough space to handle the unresolved externals that need to be
@@ -630,6 +749,9 @@
    * trampolines.
    */
-  obj->tramp_size +=
-    rtems_rtl_elf_relocate_tramp_max_size () * unresolved;
+  obj->tramps_size += obj->tramp_size * unresolved;
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+    printf ("rtl: tramp:elf: slots: %zu (%zu)\n",
+            obj->tramp_size == 0 ? 0 : obj->tramps_size / obj->tramp_size,
+            obj->tramps_size);
   return rtems_rtl_obj_alloc_trampoline (obj);
 }
@@ -654,8 +776,8 @@
 
 static bool
-rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
-                       int                 fd,
-                       rtems_rtl_obj_sect* sect,
-                       void*               data)
+rtems_rtl_elf_symbols_load (rtems_rtl_obj*      obj,
+                            int                 fd,
+                            rtems_rtl_obj_sect* sect,
+                            void*               data)
 {
   rtems_rtl_obj_cache* symbols;
@@ -721,17 +843,18 @@
      */
     if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
-      printf ("rtl: sym:elf:%-2d name:%-2d:%-20s bind:%-2d " \
-              "type:%-2d sect:%d size:%d\n",
+      printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: bind:%-2d " \
+              "type:%-2d sect:%-5d size:%-5d value:%d\n",
               sym, (int) symbol.st_name, name,
               (int) ELF_ST_BIND (symbol.st_info),
               (int) ELF_ST_TYPE (symbol.st_info),
               symbol.st_shndx,
-              (int) symbol.st_size);
-
-            /*
-         * If a duplicate forget it.
-         */
-        if (rtems_rtl_symbol_global_find (name))
-          continue;
+              (int) symbol.st_size,
+              (int) symbol.st_value);
+
+    /*
+     * If a duplicate forget it.
+     */
+    if (rtems_rtl_symbol_global_find (name))
+      continue;
 
     if ((symbol.st_shndx != 0) &&
@@ -776,5 +899,5 @@
           {
             if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
-              printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: global\n",
+              printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: global\n",
                       sym, (int) symbol.st_name, name);
             ++globals;
@@ -785,5 +908,5 @@
         {
           if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
-            printf ("rtl: sym:elf:%-2d name:%-2d:%-20s: local\n",
+            printf ("rtl: sym:elf:%-4d name:%-4d: %-20s: local\n",
                     sym, (int) symbol.st_name, name);
           ++locals;
@@ -850,5 +973,5 @@
                                          &symbol, sizeof (symbol)))
     {
-      if (locals)
+      if (obj->local_syms)
       {
         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->local_table);
@@ -857,5 +980,5 @@
         obj->local_syms = 0;
       }
-      if (globals)
+      if (obj->global_syms)
       {
         rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_SYMBOL, obj->global_table);
@@ -876,76 +999,111 @@
           (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
     {
+      rtems_rtl_obj_sym* osym;
+      char*              string;
+      Elf_Word           value;
+      const char*        name;
+
+      off = obj->ooffset + strtab->offset + symbol.st_name;
+      len = RTEMS_RTL_ELF_STRING_MAX;
+
+      if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
+        return false;
+
+      /*
+       * If a duplicate forget it.
+       */
+      if (rtems_rtl_symbol_global_find (name))
+        continue;
+
+      if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
+          (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
+      {
+        osym = gsym;
+        string = gstring;
+        gstring += strlen (name) + 1;
+        ++gsym;
+      }
+      else
+      {
+        osym = lsym;
+        string = lstring;
+        lstring += strlen (name) + 1;
+        ++lsym;
+      }
+
+      /*
+       * Allocate any common symbols in the common section.
+       */
+      if (symbol.st_shndx == SHN_COMMON)
+      {
+        size_t value_off = rtems_rtl_obj_align (common_offset,
+                                                symbol.st_value);
+        common_offset = value_off + symbol.st_size;
+        value = value_off;
+      }
+      else
+      {
+        value = symbol.st_value;
+      }
+
+      rtems_chain_set_off_chain (&osym->node);
+      memcpy (string, name, strlen (name) + 1);
+      osym->name = string;
+      osym->value = (uint8_t*) value;
+      osym->data = symbol.st_shndx;
+
+      if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+        printf ("rtl: sym:add:%-4d name:%-4d: %-20s: bind:%-2d " \
+                "type:%-2d val:%-8p sect:%-3d size:%d\n",
+                sym, (int) symbol.st_name, osym->name,
+                (int) ELF_ST_BIND (symbol.st_info),
+                (int) ELF_ST_TYPE (symbol.st_info),
+                osym->value, symbol.st_shndx,
+                (int) symbol.st_size);
+    }
+  }
+
+  return true;
+}
+
+static bool
+rtems_rtl_elf_symbols_locate (rtems_rtl_obj*      obj,
+                              int                 fd,
+                              rtems_rtl_obj_sect* sect,
+                              void*               data)
+{
+  int sym;
+
+  for (sym = 0; sym < obj->local_syms; ++sym)
+  {
+      rtems_rtl_obj_sym*  osym = &obj->local_table[sym];
       rtems_rtl_obj_sect* symsect;
-      rtems_rtl_obj_sym*  osym;
-      char*               string;
-      Elf_Word            value;
-
-      symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
+      symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
       if (symsect)
       {
-        const char* name;
-
-        off = obj->ooffset + strtab->offset + symbol.st_name;
-        len = RTEMS_RTL_ELF_STRING_MAX;
-
-        if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
-          return false;
-
-        /*
-         * If a duplicate forget it.
-         */
-        if (rtems_rtl_symbol_global_find (name))
-          continue;
-
-        if ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
-            (ELF_ST_BIND (symbol.st_info) == STB_WEAK))
-        {
-          osym = gsym;
-          string = gstring;
-          gstring += strlen (name) + 1;
-          ++gsym;
-        }
-        else
-        {
-          osym = lsym;
-          string = lstring;
-          lstring += strlen (name) + 1;
-          ++lsym;
-        }
-
-        /*
-         * Allocate any common symbols in the common section.
-         */
-        if (symbol.st_shndx == SHN_COMMON)
-        {
-          size_t value_off = rtems_rtl_obj_align (common_offset,
-                                                  symbol.st_value);
-          common_offset = value_off + symbol.st_size;
-          value = value_off;
-        }
-        else
-        {
-          value = symbol.st_value;
-        }
-
-        rtems_chain_set_off_chain (&osym->node);
-        memcpy (string, name, strlen (name) + 1);
-        osym->name = string;
-        osym->value = value + (uint8_t*) symsect->base;
-        osym->data = symbol.st_info;
-
+        osym->value += (intptr_t) symsect->base;
         if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
-          printf ("rtl: sym:add:%-2d name:%-2d:%-20s bind:%-2d " \
-                  "type:%-2d val:%8p sect:%d size:%d\n",
-                  sym, (int) symbol.st_name, osym->name,
-                  (int) ELF_ST_BIND (symbol.st_info),
-                  (int) ELF_ST_TYPE (symbol.st_info),
-                  osym->value, symbol.st_shndx,
-                  (int) symbol.st_size);
-      }
-    }
-  }
-
-  if (globals)
+          printf ("rtl: sym:locate:local :%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
+                  sym, osym->name, osym->value, osym->data,
+                  symsect->name, symsect->base);
+      }
+  }
+
+  for (sym = 0; sym < obj->global_syms; ++sym)
+  {
+      rtems_rtl_obj_sym*  osym = &obj->global_table[sym];
+      rtems_rtl_obj_sect* symsect;
+      symsect = rtems_rtl_obj_find_section_by_index (obj, osym->data);
+      if (symsect)
+      {
+        osym->value += (intptr_t) symsect->base;
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_SYMBOL))
+          printf ("rtl: sym:locate:global:%-4d name: %-20s val:%-8p sect:%-3d (%s, %p)\n",
+                  sym, osym->name, osym->value, osym->data,
+                  symsect->name, symsect->base);
+      }
+  }
+
+  if (obj->global_size)
     rtems_rtl_symbol_obj_add (obj);
 
@@ -1436,4 +1594,9 @@
 
   /*
+   * Set the format's architecture's maximum tramp size.
+   */
+  obj->tramp_size = rtems_rtl_elf_relocate_tramp_max_size ();
+
+  /*
    * Parse the section information first so we have the memory map of the object
    * file and the memory allocated. Any further allocations we make to complete
@@ -1444,6 +1607,15 @@
 
   /*
-   * See if there are any common variables and if there are add a common
-   * section.
+   * Set the entry point if there is one.
+   */
+  obj->entry = (void*)(uintptr_t) ehdr.e_entry;
+
+  /*
+   * Load the symbol table.
+   *
+   * 1. See if there are any common variables and if there are add a
+   *    common section.
+   * 2. Add up the common.
+   * 3.
    */
   if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_common, &common))
@@ -1451,9 +1623,13 @@
   if (!rtems_rtl_elf_add_common (obj, common.size, common.alignment))
     return false;
-
-  /*
-   * Set the entry point if there is one.
-   */
-  obj->entry = (void*)(uintptr_t) ehdr.e_entry;
+  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_load, &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;
 
   /*
@@ -1469,4 +1645,18 @@
     return false;
 
+  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols_locate, &ehdr))
+    return false;
+
+  if (!rtems_rtl_elf_dependents (obj, &relocs))
+    return false;
+
+  if (!rtems_rtl_elf_alloc_trampoline (obj, relocs.unresolved))
+    return false;
+
+  /*
+   * Unlock the allocator.
+   */
+  rtems_rtl_alloc_unlock ();
+
   /*
    * Load the sections and symbols and then relocation to the base address.
@@ -1476,24 +1666,6 @@
 
   /*
-   * 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;
-
-  /*
-   * Unlock the allocator.
-   */
-  rtems_rtl_alloc_unlock ();
-
-  if (!rtems_rtl_obj_load_symbols (obj, fd, rtems_rtl_elf_symbols, &ehdr))
-    return false;
-
+   * Fix up the relocations.
+   */
   if (!rtems_rtl_obj_relocate (obj, fd, rtems_rtl_elf_relocs_locator, &ehdr))
     return false;
Index: cpukit/libdl/rtl-elf.h
===================================================================
--- cpukit/libdl/rtl-elf.h	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-elf.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -51,4 +51,15 @@
  ** Imported NetBSD ELF Specifics End.
  **/
+
+/**
+ * ELF Relocation status codes.
+ */
+typedef enum rtems_rtl_elf_rel_status
+{
+  rtems_rtl_elf_rel_no_error,    /**< There is no error processing the record. */
+  rtems_rtl_elf_rel_failure,     /**< There was a failure processing the record. */
+  rtems_rtl_elf_rel_tramp_cache, /**< The reloc record may need a trampoliine. */
+  rtems_rtl_elf_rel_tramp_add    /**< Add a trampoliine. */
+} rtems_rtl_elf_rel_status;
 
 /**
@@ -144,18 +155,17 @@
  *
  * @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);
+ * @param rela 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 rtems_rtl_elf_rel_status The result of the trampoline parsing.
+ */
+rtems_rtl_elf_rel_status 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);
 
 /**
@@ -170,13 +180,12 @@
  * @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);
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
+ */
+rtems_rtl_elf_rel_status  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);
 
 /**
@@ -191,13 +200,12 @@
  * @param syminfo The ELF symbol info field.
  * @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation has been applied.
- * @retval bool The relocation could not be applied.
- */
-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);
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
+ */
+rtems_rtl_elf_rel_status 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);
 
 /**
@@ -212,13 +220,12 @@
  * @param syminfo The ELF symbol info field.
  * @param symvalue If a symbol is referenced, this is the symbols value.
- * @retval bool The relocation has been applied.
- * @retval bool The relocation could not be applied.
- */
-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);
+ * @retval rtems_rtl_elf_rel_status The result of the trampoline parsing.
+ */
+rtems_rtl_elf_rel_status 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);
 
 /**
Index: cpukit/libdl/rtl-mdreloc-arm.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-arm.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-arm.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -148,5 +148,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -163,8 +163,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -181,8 +181,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-static bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+static rtems_rtl_elf_rel_status
 rtems_rtl_elf_reloc_rel (rtems_rtl_obj*            obj,
                          const Elf_Rel*            rel,
@@ -210,20 +210,33 @@
     case R_TYPE(CALL):    /* BL/BLX */
     case R_TYPE(JUMP24):  /* B/BL<cond> */
-      insn = *where;
-
-      if (insn & 0x00800000)
-        addend = insn | 0xff000000;
-      else addend = insn & 0x00ffffff;
-
-      if (isThumb(symvalue)) {
-        if ((insn & 0xfe000000) == 0xfa000000);         /* Already blx */
-        else {
-          if ((insn & 0xff000000) == 0xeb000000) {      /* BL <label> */
-            *where = (insn & 0x00ffffff) | 0xfa000000;  /* BL-->BLX */
-          } else {
-            printf("JUMP24 is not suppored from arm to thumb\n");
-            return false;
+      if (parsing)
+      {
+        addend = 0;
+      }
+      else
+      {
+        insn = *where;
+
+        if (insn & 0x00800000)
+          addend = insn | 0xff000000;
+        else addend = insn & 0x00ffffff;
+
+        if (isThumb(symvalue)) {
+          if ((insn & 0xfe000000) == 0xfa000000);         /* Already blx */
+          else {
+            if ((insn & 0xff000000) == 0xeb000000) {      /* BL <label> */
+              *where = (insn & 0x00ffffff) | 0xfa000000;  /* BL-->BLX */
+            } else {
+              printf("JUMP24 is not suppored from arm to thumb\n");
+              return rtems_rtl_elf_rel_failure;
+            }
           }
         }
+      }
+
+      if (parsing && sect->base == 0) {
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: JUMP24/PC24/CALL tramp cache\n");
+        return rtems_rtl_elf_rel_tramp_cache;
       }
 
@@ -236,13 +249,14 @@
 
         if (parsing) {
-          obj->tramp_size += tramp_size;
-          return true;
-        }
-
-        if (!rtems_rtl_obj_has_ramp_space (obj, tramp_size)) {
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: JUMP24/PC24/CALL tramp add\n");
+          return rtems_rtl_elf_rel_tramp_add;
+        }
+
+        if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
           rtems_rtl_set_error (EINVAL,
                                "%s: CALL/JUMP24: overflow: no tramp memory",
                                sect->name);
-          return false;
+          return rtems_rtl_elf_rel_failure;
         }
 
@@ -287,5 +301,5 @@
         if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
           printf("MOVT_ABS Overflow\n");
-          return false;
+          return rtems_rtl_elf_rel_failure;
         }
       }
@@ -368,11 +382,20 @@
       /* same as THM_PC22; insn b.w */
     case R_TYPE(THM_PC22):
-      upper_insn = *(uint16_t *)where;
-      lower_insn = *((uint16_t *)where + 1);
-      sign = (upper_insn & (1 << 10)) >> 10;
-      i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
-      i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
-      tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
-      addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+      if (parsing)
+      {
+        addend = 0;
+        upper_insn = 0;
+        lower_insn = 0;
+      }
+      else
+      {
+        upper_insn = *(uint16_t *)where;
+        lower_insn = *((uint16_t *)where + 1);
+        sign = (upper_insn & (1 << 10)) >> 10;
+        i1 = ((lower_insn >> 13) & 1) ^ sign ? 0 : 1;
+        i2 = ((lower_insn >> 11) & 1) ^ sign ? 0 : 1;
+        tmp = (i1 << 23) | (i2 << 22) | ((upper_insn & 0x3ff) << 12) | ((lower_insn & 0x7ff) << 1);
+        addend = (tmp | ((sign ? 0 : 1) << 24)) - (1 << 24);
+      }
 
       if (isThumb(symvalue)) ;/*Thumb to Thumb call, nothing to care */
@@ -382,11 +405,17 @@
 #if !ALLOW_UNTESTED_RELOCS
           printf("THM_JUMP24 to arm not supported\n");
-          return false;
+          return rtems_rtl_elf_rel_failure;
 #endif
         }
         else {
           /* THM_CALL bl-->blx */
-          lower_insn &=~(1<<12);
-        }
+          lower_insn &= ~(1<<12);
+        }
+      }
+
+      if (parsing && sect->base == 0) {
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: THM_CALL/JUMP24 tramp cache\n");
+        return rtems_rtl_elf_rel_tramp_cache;
       }
 
@@ -395,17 +424,19 @@
 
       if (((Elf_Sword)tmp > 0x7fffff) || ((Elf_Sword)tmp < -0x800000)) {
-          Elf_Word tramp_addr;
-          size_t   tramp_size = get_veneer_size(ELF_R_TYPE(rel->r_info));
+        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)) {
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: THM_CALL/JUMP24 tramp add: %08x - %p = %i\n",
+                    symvalue + addend, where, (Elf_Sword) tmp);
+          return rtems_rtl_elf_rel_tramp_add;
+        }
+
+        if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
           rtems_rtl_set_error (EINVAL,
                                "%s: THM_CALL/JUMP24: overflow: no tramp memory",
                                sect->name);
-          return false;
+          return rtems_rtl_elf_rel_failure;
         }
 
@@ -439,5 +470,5 @@
       if (!isThumb(symvalue)) {
         printf("THM_JUMP19 to arm not supported\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -464,6 +495,5 @@
                              "THM_JUMP19 relocations",
                              sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
-        return true;
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -512,11 +542,11 @@
                            "in non-PLT relocations",
                            sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -535,5 +565,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
Index: cpukit/libdl/rtl-mdreloc-bfin.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-bfin.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-bfin.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -74,5 +74,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -88,8 +88,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -137,5 +137,5 @@
       if ((tmp & 0xff000000) && (~tmp & 0xff800000)) {
         printf("PCREL24/PCREL24_JU Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -153,5 +153,5 @@
       if ((tmp & 0xfffff000) && (~tmp & 0xfffff800)) {
         printf("PCREL12_JUMP_S Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -162,13 +162,13 @@
     default:
       printf("Unspported rela type\n");
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
   memcpy((void*)where, &tmp, size);
 
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -185,8 +185,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -203,5 +203,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-h8300.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-h8300.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-h8300.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -67,5 +67,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -81,8 +81,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -131,5 +131,5 @@
       if (((Elf32_Sword)tmp > 0x7f) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x80)){
         printf("PCREL8 overflow\n");
-          return false;
+          return rtems_rtl_elf_rel_failure;
       } else {
         *(uint8_t *)where = tmp;
@@ -142,5 +142,5 @@
       if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x8000)){
         printf("PCREL16 overflow\n");
-       return false;
+       return rtems_rtl_elf_rel_failure;
       } else {
        *(uint16_t *)where = tmp;
@@ -151,10 +151,10 @@
       rtems_rtl_set_error (EINVAL, "rela type record not supported");
       printf("Unsupported reloc types\n");
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*           obj,
                                   const Elf_Rel*            rel,
@@ -171,8 +171,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -189,5 +189,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-i386.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-i386.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-i386.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -74,5 +74,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -89,8 +89,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rel,
@@ -107,8 +107,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -124,8 +124,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -189,8 +189,8 @@
                            "in non-PLT relocations",
                            sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
+  return rtems_rtl_elf_rel_no_error;
 }
 
Index: cpukit/libdl/rtl-mdreloc-lm32.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-lm32.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-lm32.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -67,5 +67,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -81,8 +81,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -152,5 +152,5 @@
       if (((Elf32_Sword)tmp > 0x7fff) || ((Elf32_Sword)tmp < -0x8000)){
         printf("BRANCH Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -165,5 +165,5 @@
       rtems_rtl_set_error (EINVAL, "rela type record not supported");
       printf("Unsupported reloc types\n");
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
@@ -172,8 +172,9 @@
       printf("relocated address 0x%08lx\n", (Elf_Addr)where);
   }
-  return true;
-}
-
-bool
+
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -190,8 +191,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -208,5 +209,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-m68k.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-m68k.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-m68k.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -87,5 +87,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -101,8 +101,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -119,89 +119,89 @@
 
   switch (ELF_R_TYPE(rela->r_info)) {
-		case R_TYPE(NONE):
-			break;
-
-    case R_TYPE(PC8):
-      tmp = symvalue + rela->r_addend - (Elf_Addr)where;
-      if (overflow_8_check(tmp))
-        return false;
-
-      *(uint8_t *)where = tmp;
-
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
-                sect->name, (void*) (symvalue + rela->r_addend),
-                (void *)*where, rtems_rtl_obj_oname (obj));
-      break;
-
-    case R_TYPE(PC16):
-      tmp = symvalue + rela->r_addend - (Elf_Addr)where;
-      if (overflow_16_check(tmp))
-        return false;
-
-      *(uint16_t*)where = tmp;
-
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
-                sect->name, (void*) (symvalue + rela->r_addend),
-                (void *)*where, rtems_rtl_obj_oname (obj));
-      break;
-		case R_TYPE(PC32):
-      target = (Elf_Addr) symvalue + rela->r_addend;
-      *where += target - (Elf_Addr)where;
-
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
-                sect->name, (void*) (symvalue + rela->r_addend),
-                (void *)*where, rtems_rtl_obj_oname (obj));
-      break;
-
-		case R_TYPE(GOT32):
-		case R_TYPE(32):
-		case R_TYPE(GLOB_DAT):
-      target = (Elf_Addr) symvalue + rela->r_addend;
-
-			if (*where != target)
-				*where = target;
-
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
-                sect->name, (void *)*where,
-                rtems_rtl_obj_oname (obj));
-			break;
-
-		case R_TYPE(RELATIVE):
-			*where += (Elf_Addr) sect->base + rela->r_addend;
-      if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-        printf ("rtl: reloc RELATIVE in %s --> %p\n",
-                rtems_rtl_obj_oname (obj), (void *)*where);
-			break;
-
-		case R_TYPE(COPY):
-			/*
-			 * These are deferred until all other relocations have
-			 * been done.  All we do here is make sure that the
-			 * COPY relocation is not in a shared library.  They
-			 * are allowed only in executable files.
-			 */
-      printf ("rtl: reloc COPY (please report)\n");
-			break;
-
-		default:
-      printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
-              "contents = %p\n",
-              ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
-              (void *)rela->r_offset, (void *)*where);
-      rtems_rtl_set_error (EINVAL,
-                           "%s: Unsupported relocation type %d "
-                           "in non-PLT relocations",
-                           sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
-      return false;
+  case R_TYPE(NONE):
+    break;
+
+  case R_TYPE(PC8):
+    tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+    if (overflow_8_check(tmp))
+      return rtems_rtl_elf_rel_failure;
+
+    *(uint8_t *)where = tmp;
+
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: reloc R_TYPE_8/PC8 in %s --> %p (%p) in %s\n",
+              sect->name, (void*) (symvalue + rela->r_addend),
+              (void *)*where, rtems_rtl_obj_oname (obj));
+    break;
+
+  case R_TYPE(PC16):
+    tmp = symvalue + rela->r_addend - (Elf_Addr)where;
+    if (overflow_16_check(tmp))
+      return rtems_rtl_elf_rel_failure;
+
+    *(uint16_t*)where = tmp;
+
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: reloc R_TYPE_16/PC16 in %s --> %p (%p) in %s\n",
+              sect->name, (void*) (symvalue + rela->r_addend),
+              (void *)*where, rtems_rtl_obj_oname (obj));
+    break;
+  case R_TYPE(PC32):
+    target = (Elf_Addr) symvalue + rela->r_addend;
+    *where += target - (Elf_Addr)where;
+
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: reloc PC32 in %s --> %p (%p) in %s\n",
+              sect->name, (void*) (symvalue + rela->r_addend),
+              (void *)*where, rtems_rtl_obj_oname (obj));
+    break;
+
+  case R_TYPE(GOT32):
+  case R_TYPE(32):
+  case R_TYPE(GLOB_DAT):
+    target = (Elf_Addr) symvalue + rela->r_addend;
+
+    if (*where != target)
+      *where = target;
+
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: reloc 32/GLOB_DAT in %s --> %p in %s\n",
+              sect->name, (void *)*where,
+              rtems_rtl_obj_oname (obj));
+    break;
+
+  case R_TYPE(RELATIVE):
+    *where += (Elf_Addr) sect->base + rela->r_addend;
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+      printf ("rtl: reloc RELATIVE in %s --> %p\n",
+              rtems_rtl_obj_oname (obj), (void *)*where);
+    break;
+
+  case R_TYPE(COPY):
+    /*
+     * These are deferred until all other relocations have
+     * been done.  All we do here is make sure that the
+     * COPY relocation is not in a shared library.  They
+     * are allowed only in executable files.
+     */
+    printf ("rtl: reloc COPY (please report)\n");
+    break;
+
+  default:
+    printf ("rtl: reloc unknown: sym = %u, type = %u, offset = %p, "
+            "contents = %p\n",
+            ELF_R_SYM(rela->r_info), (uint32_t) ELF_R_TYPE(rela->r_info),
+            (void *)rela->r_offset, (void *)*where);
+    rtems_rtl_set_error (EINVAL,
+                         "%s: Unsupported relocation type %d "
+                         "in non-PLT relocations",
+                         sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
+    return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -218,8 +218,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -236,5 +236,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-mips.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-mips.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-mips.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -67,5 +67,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -82,8 +82,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -100,8 +100,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rela type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -117,5 +117,5 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
+  return rtems_rtl_elf_rel_no_error;
 }
 
@@ -128,5 +128,5 @@
  * just consider symtype here.
  */
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -163,5 +163,5 @@
       if ((tmp & 0xffff0000) != 0) {
         printf("R_MIPS_16 Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -225,5 +225,5 @@
       tmp = symvalue;
       if (tmp == 0)
-        return false;
+        return rtems_rtl_elf_rel_failure;
 
       addend &= 0xffff0000;
@@ -255,5 +255,5 @@
       if (((Elf_Sword)tmp > 0x7fff) || ((Elf_Sword)tmp < -0x8000)) {
         printf("R_MIPS_PC16 Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -275,8 +275,8 @@
                            "in non-PLT relocations",
                            sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
+  return rtems_rtl_elf_rel_no_error;
 }
 
Index: cpukit/libdl/rtl-mdreloc-moxie.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-moxie.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-moxie.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -68,5 +68,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -82,8 +82,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
+  return rtems_rtl_elf_rel_no_error;
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -123,5 +123,5 @@
       if (((Elf32_Sword)tmp > 0x1ff) || ((Elf32_Sword)tmp < -(Elf32_Sword)0x200)){
         printf("Overflow for PCREL10: %ld exceed -0x200:0x1ff\n", tmp);
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -137,11 +137,11 @@
       rtems_rtl_set_error (EINVAL, "rela type record not supported");
       printf("Unsupported reloc types\n");
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
+  return rtems_rtl_elf_rel_no_error;
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -158,8 +158,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -176,5 +176,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-powerpc.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-powerpc.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-powerpc.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -214,5 +214,12 @@
 }
 
-static bool
+/**
+ * The offsets in the reloc words.
+ */
+#define REL_R_OFFSET (0)
+#define REL_R_INFO   (1)
+#define REL_R_ADDEND (2)
+
+static rtems_rtl_elf_rel_status
 rtems_rtl_elf_reloc_rela (rtems_rtl_obj*            obj,
                           const Elf_Rela*           rela,
@@ -227,4 +234,5 @@
   uint32_t mask = 0;
   uint32_t bits = 0;
+  bool     needs_tramp = false;
 
   where = (Elf_Addr *)(sect->base + rela->r_offset);
@@ -260,4 +268,11 @@
         mask = 0x3fffffc;
       }
+
+      if (parsing && sect->base == 0) {
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: ADDR14/ADDR24 tramp cache\n");
+        return rtems_rtl_elf_rel_tramp_cache;
+      }
+
       tmp = (symvalue + rela->r_addend) >> 2;
       if (tmp > ((1<<bits) - 1 )) {
@@ -265,7 +280,15 @@
         size_t   tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
         if (parsing) {
-          obj->tramp_size += tramp_size;
-          return true;
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: ADDR14/ADDR24 tramp add\n");
+          return rtems_rtl_elf_rel_tramp_add;
         }
+        if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: ADDR14/ADDR24 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
+          rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: ADDR14/ADDR24", sect->name);
+          return rtems_rtl_elf_rel_failure;
+        }
+        needs_tramp = true;
         tramp_addr = (Elf_Addr) obj->tramp_brk;
         obj->tramp_brk = set_veneer(obj->tramp_brk,
@@ -284,5 +307,6 @@
         *where = tmp;
         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-          printf ("rtl: ADDR14/ADDR24 %p @ %p in %s\n",
+          printf ("rtl: ADDR14/ADDR24%s %p @ %p in %s\n",
+                  needs_tramp ? "(tramp)" : "",
                   (void *)*where, where, rtems_rtl_obj_oname (obj));
       }
@@ -340,4 +364,10 @@
         mask = 0xfffc;
         bits = 14;
+      }
+
+      if (parsing && sect->base == 0) {
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: REL24/REL14 tramp cache\n");
+        return rtems_rtl_elf_rel_tramp_cache;
       }
 
@@ -348,7 +378,15 @@
         size_t   tramp_size = get_veneer_size(ELF_R_TYPE(rela->r_info));
         if (parsing) {
-          obj->tramp_size += tramp_size;
-          return true;
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: REL24/REL14 tramp add\n");
+          return rtems_rtl_elf_rel_tramp_add;
         }
+        if (!rtems_rtl_obj_has_tramp_space (obj, tramp_size)) {
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+            printf ("rtl: REL24/REL14 no tramp slot: %s\n", rtems_rtl_obj_oname (obj));
+          rtems_rtl_set_error (ENOMEM, "%s: tramp: no slot: REL24/REL14", sect->name);
+          return rtems_rtl_elf_rel_failure;
+        }
+        needs_tramp = true;
         tramp_addr = (Elf_Addr) obj->tramp_brk;
         obj->tramp_brk = set_veneer(obj->tramp_brk,
@@ -368,5 +406,6 @@
         *where = tmp;
         if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-          printf ("rtl: REL24/REL14 %p @ %p in %s\n",
+          printf ("rtl: REL24/REL14%s %p @ %p in %s\n",
+                  needs_tramp ? "(tramp)" : "",
                   (void *)*where, where, rtems_rtl_obj_oname (obj));
       }
@@ -413,10 +452,10 @@
                            "in non-PLT relocations",
                            sect->name, (uint32_t) ELF_R_TYPE(rela->r_info));
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -435,5 +474,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -452,5 +491,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -467,8 +506,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -485,5 +524,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-sparc.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-sparc.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-sparc.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -186,5 +186,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -200,8 +200,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -219,13 +219,13 @@
   type = ELF_R_TYPE(rela->r_info);
   if (type == R_TYPE(NONE))
-    return true;
+    return rtems_rtl_elf_rel_no_error;
 
   /* We do JMP_SLOTs in _rtld_bind() below */
   if (type == R_TYPE(JMP_SLOT))
-    return true;
+    return rtems_rtl_elf_rel_no_error;
 
   /* COPY relocs are also handled elsewhere */
   if (type == R_TYPE(COPY))
-    return true;
+    return rtems_rtl_elf_rel_no_error;
 
   /*
@@ -234,5 +234,5 @@
    */
   if (type > R_TYPE(6))
-    return false;
+    return rtems_rtl_elf_rel_failure;
 
   value = rela->r_addend;
@@ -246,5 +246,5 @@
       printf ("rtl: reloc relative in %s --> %p",
               rtems_rtl_obj_oname (obj), (void *)*where);
-    return true;
+    return rtems_rtl_elf_rel_no_error;
   }
 
@@ -316,8 +316,8 @@
             (void *)tmp, where, rtems_rtl_obj_oname (obj));
 
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -334,8 +334,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -352,5 +352,5 @@
   (void) symvalue;
   printf ("rtl: rel type record not supported; please report\n");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-mdreloc-v850.c
===================================================================
--- cpukit/libdl/rtl-mdreloc-v850.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-mdreloc-v850.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -68,5 +68,5 @@
 }
 
-bool
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela_tramp (rtems_rtl_obj*            obj,
                                    const Elf_Rela*           rela,
@@ -82,8 +82,8 @@
   (void) syminfo;
   (void) symvalue;
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Rela*           rela,
@@ -126,5 +126,5 @@
       if (((Elf_Sword)tmp > 0x1fffff) || ((Elf_Sword)tmp < -0x200000)) {
         printf("Overflow\n");
-        return false;
+        return rtems_rtl_elf_rel_failure;
       }
 
@@ -146,11 +146,11 @@
       rtems_rtl_set_error (EINVAL, "rela type record not supported");
       printf("error reloc type\n");
-      return false;
+      return rtems_rtl_elf_rel_failure;
   }
 
-  return true;
-}
-
-bool
+  return rtems_rtl_elf_rel_no_error;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel_tramp (rtems_rtl_obj*            obj,
                                   const Elf_Rel*            rel,
@@ -167,8 +167,8 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
-}
-
-bool
+  return rtems_rtl_elf_rel_failure;
+}
+
+rtems_rtl_elf_rel_status
 rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
                             const Elf_Rel*            rel,
@@ -185,5 +185,5 @@
   (void) symvalue;
   rtems_rtl_set_error (EINVAL, "rel type record not supported");
-  return false;
+  return rtems_rtl_elf_rel_failure;
 }
 
Index: cpukit/libdl/rtl-obj.c
===================================================================
--- cpukit/libdl/rtl-obj.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-obj.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -584,8 +584,8 @@
 rtems_rtl_obj_alloc_trampoline (rtems_rtl_obj* obj)
 {
-  if (obj->tramp_size == 0)
+  if (obj->tramps_size == 0)
     return true;
   obj->trampoline = rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT,
-                                         obj->tramp_size,
+                                         obj->tramps_size,
                                          true);
   if (obj->trampoline == NULL)
@@ -904,5 +904,5 @@
   {
     rtems_cache_instruction_sync_after_code_change(obj->trampoline,
-                                                   obj->tramp_size);
+                                                   obj->tramps_size);
   }
 }
@@ -999,4 +999,158 @@
 }
 
+static void
+rtems_rtl_obj_sections_locate (uint32_t            mask,
+                               rtems_rtl_alloc_tag tag,
+                               rtems_rtl_obj*      obj,
+                               uint8_t*            base)
+{
+  rtems_chain_control* sections = &obj->sections;
+  rtems_chain_node*    node = rtems_chain_first (sections);
+  size_t               base_offset = 0;
+  int                  order = 0;
+
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+    printf ("rtl: locating section: mask:%08" PRIx32 " base:%p\n", mask, base);
+
+  while (!rtems_chain_is_tail (sections, node))
+  {
+    rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
+
+    if ((sect->size != 0) && ((sect->flags & mask) == mask))
+    {
+      if (sect->load_order == order)
+      {
+        if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
+        {
+          base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
+          sect->base = base + base_offset;
+        }
+
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+          printf ("rtl: locating:%2d: %s -> %p (s:%zi f:%04" PRIx32
+                  " a:%" PRIu32 " l:%02d)\n",
+                  order, sect->name, sect->base, sect->size,
+                  sect->flags, sect->alignment, sect->link);
+
+        if (sect->base)
+          base_offset += sect->size;
+
+        ++order;
+
+        node = rtems_chain_first (sections);
+        continue;
+      }
+    }
+
+    node = rtems_chain_next (node);
+  }
+}
+
+bool
+rtems_rtl_obj_alloc_sections (rtems_rtl_obj*             obj,
+                              int                        fd,
+                              rtems_rtl_obj_sect_handler handler,
+                              void*                      data)
+{
+  size_t text_size;
+  size_t const_size;
+  size_t eh_size;
+  size_t data_size;
+  size_t bss_size;
+
+  text_size  = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj);
+  const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj);
+  eh_size    = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj);
+  data_size  = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj);
+  bss_size   = rtems_rtl_obj_bss_size (obj);
+
+  /*
+   * Set the sizes held in the object data. We need this for a fast reference.
+   */
+  obj->text_size  = text_size;
+  obj->const_size = const_size;
+  obj->data_size  = data_size;
+  obj->eh_size    = eh_size;
+  obj->bss_size   = bss_size;
+
+  /*
+   * Perform any specific allocations for sections.
+   */
+  if (handler != NULL)
+  {
+    if (!rtems_rtl_obj_section_handler (RTEMS_RTL_OBJ_SECT_TYPES,
+                                        obj,
+                                        fd,
+                                        handler,
+                                        data))
+    {
+      obj->exec_size = 0;
+      return false;
+    }
+  }
+
+  /*
+   * Let the allocator manage the actual allocation. The user can use the
+   * standard heap or provide a specific allocator with memory protection.
+   */
+  if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size,
+                                   &obj->const_base, const_size,
+                                   &obj->eh_base, eh_size,
+                                   &obj->data_base, data_size,
+                                   &obj->bss_base, bss_size))
+  {
+    obj->exec_size = 0;
+    rtems_rtl_set_error (ENOMEM, "no memory to load obj");
+    return false;
+  }
+
+  obj->exec_size = text_size + const_size + eh_size + data_size + bss_size;
+
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
+  {
+    printf ("rtl: load sect: text  - b:%p s:%zi a:%" PRIu32 "\n",
+            obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj));
+    printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n",
+            obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj));
+    printf ("rtl: load sect: eh    - b:%p s:%zi a:%" PRIu32 "\n",
+            obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj));
+    printf ("rtl: load sect: data  - b:%p s:%zi a:%" PRIu32 "\n",
+            obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj));
+    printf ("rtl: load sect: bss   - b:%p s:%zi a:%" PRIu32 "\n",
+            obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj));
+  }
+
+  /*
+   * Determine the load order.
+   */
+  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_TEXT,  obj);
+  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj);
+  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH,    obj);
+  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA,  obj);
+  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS,   obj);
+
+  /*
+   * Locate all text, data and bss sections in seperate operations so each type of
+   * section is grouped together.
+   */
+  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_TEXT,
+                                 rtems_rtl_alloc_text_tag (),
+                                 obj, obj->text_base);
+  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_CONST,
+                                 rtems_rtl_alloc_const_tag (),
+                                 obj, obj->const_base);
+  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_EH,
+                                 rtems_rtl_alloc_eh_tag (),
+                                 obj, obj->eh_base);
+  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_DATA,
+                                 rtems_rtl_alloc_data_tag (),
+                                 obj, obj->data_base);
+  rtems_rtl_obj_sections_locate (RTEMS_RTL_OBJ_SECT_BSS,
+                                 rtems_rtl_alloc_bss_tag (),
+                                 obj, obj->bss_base);
+
+  return true;
+}
+
 static bool
 rtems_rtl_obj_sections_loader (uint32_t                   mask,
@@ -1010,5 +1164,4 @@
   rtems_chain_control* sections = &obj->sections;
   rtems_chain_node*    node = rtems_chain_first (sections);
-  size_t               base_offset = 0;
   int                  order = 0;
 
@@ -1026,10 +1179,4 @@
       if (sect->load_order == order)
       {
-        if ((sect->flags & RTEMS_RTL_OBJ_SECT_ARCH_ALLOC) == 0)
-        {
-          base_offset = rtems_rtl_obj_align (base_offset, sect->alignment);
-          sect->base = base + base_offset;
-        }
-
         if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
           printf ("rtl: loading:%2d: %s -> %p (s:%zi f:%04" PRIx32
@@ -1059,7 +1206,4 @@
         }
 
-        if (sect->base)
-          base_offset += sect->size;
-
         ++order;
 
@@ -1073,90 +1217,4 @@
 
   rtems_rtl_alloc_wr_disable (tag, base);
-
-  return true;
-}
-
-bool
-rtems_rtl_obj_alloc_sections (rtems_rtl_obj*             obj,
-                              int                        fd,
-                              rtems_rtl_obj_sect_handler handler,
-                              void*                      data)
-{
-  size_t text_size;
-  size_t const_size;
-  size_t eh_size;
-  size_t data_size;
-  size_t bss_size;
-
-  text_size  = rtems_rtl_obj_text_size (obj) + rtems_rtl_obj_const_alignment (obj);
-  const_size = rtems_rtl_obj_const_size (obj) + rtems_rtl_obj_eh_alignment (obj);
-  eh_size    = rtems_rtl_obj_eh_size (obj) + rtems_rtl_obj_data_alignment (obj);
-  data_size  = rtems_rtl_obj_data_size (obj) + rtems_rtl_obj_bss_alignment (obj);
-  bss_size   = rtems_rtl_obj_bss_size (obj);
-
-  /*
-   * Set the sizes held in the object data. We need this for a fast reference.
-   */
-  obj->text_size  = text_size;
-  obj->const_size = const_size;
-  obj->data_size  = data_size;
-  obj->eh_size    = eh_size;
-  obj->bss_size   = bss_size;
-
-  /*
-   * Perform any specific allocations for sections.
-   */
-  if (handler != NULL)
-  {
-    if (!rtems_rtl_obj_section_handler (RTEMS_RTL_OBJ_SECT_TYPES,
-                                        obj,
-                                        fd,
-                                        handler,
-                                        data))
-    {
-      obj->exec_size = 0;
-      return false;
-    }
-  }
-
-  /*
-   * Let the allocator manage the actual allocation. The user can use the
-   * standard heap or provide a specific allocator with memory protection.
-   */
-  if (!rtems_rtl_alloc_module_new (&obj->text_base, text_size,
-                                   &obj->const_base, const_size,
-                                   &obj->eh_base, eh_size,
-                                   &obj->data_base, data_size,
-                                   &obj->bss_base, bss_size))
-  {
-    obj->exec_size = 0;
-    rtems_rtl_set_error (ENOMEM, "no memory to load obj");
-    return false;
-  }
-
-  obj->exec_size = text_size + const_size + eh_size + data_size + bss_size;
-
-  if (rtems_rtl_trace (RTEMS_RTL_TRACE_LOAD_SECT))
-  {
-    printf ("rtl: load sect: text  - b:%p s:%zi a:%" PRIu32 "\n",
-            obj->text_base, text_size, rtems_rtl_obj_text_alignment (obj));
-    printf ("rtl: load sect: const - b:%p s:%zi a:%" PRIu32 "\n",
-            obj->const_base, const_size, rtems_rtl_obj_const_alignment (obj));
-    printf ("rtl: load sect: eh    - b:%p s:%zi a:%" PRIu32 "\n",
-            obj->eh_base, eh_size, rtems_rtl_obj_eh_alignment (obj));
-    printf ("rtl: load sect: data  - b:%p s:%zi a:%" PRIu32 "\n",
-            obj->data_base, data_size, rtems_rtl_obj_data_alignment (obj));
-    printf ("rtl: load sect: bss   - b:%p s:%zi a:%" PRIu32 "\n",
-            obj->bss_base, bss_size, rtems_rtl_obj_bss_alignment (obj));
-  }
-
-  /*
-   * Determine the load order.
-   */
-  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_TEXT,  obj);
-  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_CONST, obj);
-  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_EH,    obj);
-  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_DATA,  obj);
-  rtems_rtl_obj_sections_link_order (RTEMS_RTL_OBJ_SECT_BSS,   obj);
 
   return true;
Index: cpukit/libdl/rtl-shell.c
===================================================================
--- cpukit/libdl/rtl-shell.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-shell.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -144,4 +144,5 @@
   bool                 symbols;      /**< Print the global symbols. */
   bool                 dependencies; /**< Print any dependencies. */
+  bool                 trampolines;  /**< Print trampoline stats. */
   bool                 base;         /**< Include the base object file. */
   const char*          re_name;      /**< Name regx to filter on. */
@@ -516,4 +517,6 @@
     rtems_printf (print->printer, "%-*cusers         : %zu\n", indent, ' ', obj->users);
     rtems_printf (print->printer, "%-*creferences    : %zu\n", indent, ' ', obj->refs);
+    rtems_printf (print->printer, "%-*ctrampolines   : %zu\n", indent, ' ',
+                  rtems_rtl_obj_trampolines (obj));
     rtems_printf (print->printer, "%-*csymbols       : %zi\n", indent, ' ', obj->global_syms);
     rtems_printf (print->printer, "%-*csymbol memory : %zi\n", indent, ' ', obj->global_size);
@@ -536,4 +539,31 @@
       rtems_printf (print->printer, "\n");
   }
+  if (print->trampolines)
+  {
+    if (obj->tramp_size == 0)
+    {
+      rtems_printf (print->printer, "%-*ctrampolines: not supported\n", indent, ' ');
+    }
+    else
+    {
+      size_t slots = rtems_rtl_obj_trampoline_slots (obj);
+      size_t used = rtems_rtl_obj_trampolines (obj);
+      rtems_printf (print->printer, "%-*ctrampolines:\n", indent, ' ');
+      rtems_printf (print->printer, "%-*cslots     : %zu\n", indent + 4, ' ',
+                    slots);
+      rtems_printf (print->printer, "%-*csize      : %zu\n", indent + 4, ' ',
+                    obj->tramps_size);
+      rtems_printf (print->printer, "%-*cslot size : %zu\n", indent + 4, ' ',
+                    obj->tramp_size);
+      rtems_printf (print->printer, "%-*cused      : %zu\n", indent + 4, ' ',
+                    used);
+      rtems_printf (print->printer, "%-*crelocs    : %zu\n", indent + 4, ' ',
+                    obj->tramp_relocs);
+      rtems_printf (print->printer, "%-*cunresolved: %zu\n", indent + 4, ' ',
+                    slots - obj->tramp_relocs);
+      rtems_printf (print->printer, "%-*cyield     : %zu%%\n", indent + 4, ' ',
+                    slots ? (used * 100) / slots : 0);
+    }
+  }
   return true;
 }
@@ -568,16 +598,29 @@
 {
   rtems_rtl_obj_print print = { 0 };
-  if (!rtems_rtl_check_opts (printer, "nlmsdb", argc, argv))
+  if (!rtems_rtl_check_opts (printer, "anlmsdbt", argc, argv))
     return 1;
   print.printer = printer;
   print.indent = 1;
   print.oname = true;
-  print.names = rtems_rtl_parse_opt ('n', argc, argv);
-  print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
-  print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
-  print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
-  print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
-  print.base = rtems_rtl_parse_opt ('b', argc, argv);;
-  print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+  if (rtems_rtl_parse_opt ('a', argc, argv))
+  {
+    print.names = true;
+    print.stats = true;
+    print.memory_map = true;
+    print.symbols = true;
+    print.dependencies = true;
+    print.trampolines = true;
+  }
+  else
+  {
+    print.names = rtems_rtl_parse_opt ('n', argc, argv);
+    print.stats = rtems_rtl_parse_opt ('l', argc, argv);;
+    print.memory_map = rtems_rtl_parse_opt ('m', argc, argv);;
+    print.symbols = rtems_rtl_parse_opt ('s', argc, argv);
+    print.dependencies = rtems_rtl_parse_opt ('d', argc, argv);;
+    print.trampolines = rtems_rtl_parse_opt ('t', argc, argv);;
+    print.base = rtems_rtl_parse_opt ('b', argc, argv);;
+    print.re_name = rtems_rtl_parse_arg (' ', NULL, argc, argv);
+  }
   print.re_symbol = NULL;
   print.rtl = rtems_rtl_lock ();
Index: cpukit/libdl/rtl-trampoline.h
===================================================================
--- cpukit/libdl/rtl-trampoline.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
+++ cpukit/libdl/rtl-trampoline.h	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -0,0 +1,94 @@
+/*
+ *  COPYRIGHT (c) 2019 Chris Johns <chrisj@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.
+ */
+/**
+ * @file
+ *
+ * @ingroup rtems_rtl
+ *
+ * @brief RTEMS Run-Time Linker Object File Trampoline Relocations Table.
+ *
+ * Cache relocation records that could result in a trampoline. The unresolved
+ * symbol table holds variable the symbol name (length string) and the object
+ * file's relocation records that reference the unresolved symbol. The
+ * trampoline cache is an extension to this table to reuse the code and memory
+ * and support trampolines.
+ *
+ * Some architectures require trampolines or veneers to extend the range of
+ * some instructions. The compiler generates small optimized instructions
+ * assuming most destinations are within the range of the instruction. The
+ * instructions are smaller in size and can have a number of encodings with
+ * different ranges. If a relocation record points to a symbol that is out of
+ * range for the instruction a trampoline is used to extend the instruction's
+ * range. A trampoline is a small fragment of architecture specific
+ * instructions located within the range of the relocation record instruction
+ * that can reach the entire address range. The trampoline's execution is
+ * transparent to the execution of the object file.
+ *
+ * An object file that needs a trampoline has a table allocated close to the
+ * text section. It has to be close to ensure the largest possible object file
+ * can be spported. The number of slots in a table depends on:
+ *
+ *  # Location of the code
+ *  # The type of relocation records in the object file
+ *  # The instruction encoding the relocation record points too
+ *  # The landing address of the instruction
+ *
+ * The allocation of the text segment and the trampoline table have to happen
+ * with the allocator lock being locked and held to make sure no other
+ * allocations happen inbetween the text section allocation and the trampoline
+ * table. Holding an allocator lock limits what the link editor can do when
+ * when the default heap allocator is being used. If calls any operating
+ * system services including the file system use the same allocator a deadlock
+ * will occur. This creates a conflict between performing the allocations
+ * together and reading the instructions while holding the allocator lock.
+ *
+ * The trampoline cache holds the parsed relocation records that could result
+ * in a trampoline. These records can be exaimined after the allocation of the
+ * text segment to determine how many relocation record target's are out of
+ * range. The minimum range for a specific type of relocation record has to be
+ * used as the instructions cannot be loaded.
+ */
+
+#if !defined (_RTEMS_RTL_TRAMPOLINE_H_)
+#define _RTEMS_RTL_TRAMPOLINE_H_
+
+#include <rtems/rtl/rtl-unresolved.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * Add a relocation to the list of trampolinr relocations.
+ *
+ * @param obj The object table the relocation record is for.
+ * @param flags Format specific flags.
+ * @param sect The target section number the relocation references.
+ * @param symvalue The symbol's value.
+ * @param rel The format specific relocation data.
+ * @retval true The relocation has been added.
+ * @retval false The relocation could not be added.
+ */
+bool rtems_rtl_trampoline_add (rtems_rtl_obj*        obj,
+                               const uint16_t        flags,
+                               const uint16_t        sect,
+                               const rtems_rtl_word  symvalue,
+                               const rtems_rtl_word* rel);
+
+/**
+ * Remove the relocation records for an object file.
+ *
+ * @param obj The object table the symbols are for.
+ */
+void rtems_rtl_trampoline_remove (rtems_rtl_obj* obj);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif
Index: cpukit/libdl/rtl-unresolved.c
===================================================================
--- cpukit/libdl/rtl-unresolved.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl-unresolved.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -28,4 +28,5 @@
 #include <rtems/rtl/rtl-unresolved.h>
 #include <rtems/rtl/rtl-trace.h>
+#include "rtl-trampoline.h"
 
 static rtems_rtl_unresolv_block*
@@ -70,5 +71,5 @@
 static int
 rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
-                                rtems_rtl_unresolv_rec* rec)
+                                rtems_rtl_unresolv_rec*   rec)
 {
   return rec - &block->rec[0];
@@ -102,4 +103,5 @@
 
     case rtems_rtl_unresolved_reloc:
+    case rtems_rtl_trampoline_reloc:
       ++rec;
       break;
@@ -402,4 +404,23 @@
   bytes = count * sizeof (rtems_rtl_unresolv_rec);
   memset (&block->rec[block->recs], 0, bytes);
+}
+
+static rtems_chain_node*
+rtems_rtl_unresolved_delete_block_if_empty (rtems_chain_control*      blocks,
+                                            rtems_rtl_unresolv_block* block)
+{
+  rtems_chain_node* node = &block->link;
+  rtems_chain_node* next_node = rtems_chain_next (node);
+  /*
+   * Always leave a single block allocated. Eases possible heap fragmentation.
+   */
+  if (block->recs == 0 && !rtems_chain_has_only_one_node (blocks))
+  {
+    if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+      printf ("rtl: unresolv: block-del %p\n", block);
+    rtems_chain_extract (node);
+    rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
+  }
+  return next_node;
 }
 
@@ -457,17 +478,6 @@
       }
 
-      if (block->recs == 0)
-      {
-        rtems_chain_node* next_node = rtems_chain_next (node);
-        if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
-          printf ("rtl: unresolv: block-del %p\n", block);
-        rtems_chain_extract (node);
-        rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_EXTERNAL, block);
-        node = next_node;
-      }
-      else
-      {
-        node = rtems_chain_next (node);
-      }
+      node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
+                                                         block);
     }
   }
@@ -481,5 +491,5 @@
   unresolved->block_recs = block_recs;
   rtems_chain_initialize_empty (&unresolved->blocks);
-  return true;
+  return rtems_rtl_unresolved_block_alloc (unresolved);
 }
 
@@ -633,11 +643,11 @@
   /*
    * The resolving process is two separate stages, The first stage is to
-   * iterate over the unresolved symbols search the global symbol table. If a
-   * symbol is found iterate over the unresolved relocation records for the
+   * iterate over the unresolved symbols searching the global symbol table. If
+   * a symbol is found iterate over the unresolved relocation records for the
    * symbol fixing up the relocations. The second stage is to search the
-   * archives for symbols we have not been search before and if a symbol if
-   * found in an archve loaded the object file. Loading an object file stops
-   * the search of the archives for symbols and stage one is performed
-   * again. The process repeats until no more symbols are resolved.
+   * archives for symbols we have not searched before and if a symbol is found
+   * in an archve load the object file. Loading an object file stops the
+   * search of the archives for symbols and stage one is performed again. The
+   * process repeats until no more symbols are resolved or there is an error.
    */
   while (resolving)
@@ -666,14 +676,83 @@
 
 bool
-rtems_rtl_unresolved_remove (rtems_rtl_obj*        obj,
-                             const char*           name,
-                             const uint16_t        sect,
-                             const rtems_rtl_word* rel)
-{
-  rtems_rtl_unresolved* unresolved;
+rtems_rtl_trampoline_add (rtems_rtl_obj*        obj,
+                          const uint16_t        flags,
+                          const uint16_t        sect,
+                          const rtems_rtl_word  symvalue,
+                          const rtems_rtl_word* rel)
+{
+  rtems_rtl_unresolved*     unresolved;
+  rtems_rtl_unresolv_block* block;
+  rtems_rtl_unresolv_rec*   rec;
+
+  if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
+    printf ("rtl: tramp: add: %s sect:%d flags:%04x\n",
+            rtems_rtl_obj_oname (obj), sect, flags);
+
   unresolved = rtems_rtl_unresolved_unprotected ();
-  if (unresolved == NULL)
+  if (!unresolved)
     return false;
+
+  block = rtems_rtl_unresolved_alloc_recs (unresolved, 1);
+  if (block == NULL)
+  {
+    block = rtems_rtl_unresolved_block_alloc (unresolved);
+    if (!block)
+      return false;
+  }
+
+  rec = rtems_rtl_unresolved_rec_first_free (block);
+  rec->type = rtems_rtl_trampoline_reloc;
+  rec->rec.tramp.obj = obj;
+  rec->rec.tramp.flags = flags;
+  rec->rec.tramp.sect = sect;
+  rec->rec.tramp.symvalue = symvalue;
+  rec->rec.tramp.rel[0] = rel[0];
+  rec->rec.tramp.rel[1] = rel[1];
+  rec->rec.tramp.rel[2] = rel[2];
+
+  ++block->recs;
+
   return true;
+}
+
+void
+rtems_rtl_trampoline_remove (rtems_rtl_obj* obj)
+{
+  rtems_rtl_unresolved* unresolved = rtems_rtl_unresolved_unprotected ();
+  if (unresolved)
+  {
+    /*
+     * Iterate over the blocks clearing any trampoline records.
+     */
+    rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
+    while (!rtems_chain_is_tail (&unresolved->blocks, node))
+    {
+      rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
+      rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
+
+      /*
+       * Search the table for a trampoline record and if found clean the
+       * record moving the remaining records down the block.
+       */
+      while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+      {
+        bool next_rec = true;
+
+        if (rec->type == rtems_rtl_trampoline_reloc && rec->rec.tramp.obj == obj)
+        {
+            rtems_rtl_unresolved_clean_block (block, rec, 1,
+                                              unresolved->block_recs);
+            next_rec = false;
+        }
+
+        if (next_rec)
+          rec = rtems_rtl_unresolved_rec_next (rec);
+      }
+
+      node = rtems_rtl_unresolved_delete_block_if_empty (&unresolved->blocks,
+                                                         block);
+    }
+  }
 }
 
@@ -709,6 +788,8 @@
     break;
   case rtems_rtl_unresolved_reloc:
+  case rtems_rtl_trampoline_reloc:
     if (dd->show_relocs)
-      printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
+      printf (" %3zu: 2:reloc%c: obj:%s name:%2d: sect:%d\n",
+              rec->type == rtems_rtl_unresolved_reloc ? 'R' : 'T',
               dd->rec,
               rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
Index: cpukit/libdl/rtl.c
===================================================================
--- cpukit/libdl/rtl.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ cpukit/libdl/rtl.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -478,19 +478,22 @@
 rtems_rtl_find_obj_with_symbol (const rtems_rtl_obj_sym* sym)
 {
-  rtems_chain_node* node = rtems_chain_first (&rtl->objects);
-  while (!rtems_chain_is_tail (&rtl->objects, node))
-  {
-    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
-    if (rtems_rtl_obj_has_symbol (obj, sym))
-      return obj;
-    node = rtems_chain_next (node);
-  }
-  node = rtems_chain_first (&rtl->pending);
-  while (!rtems_chain_is_tail (&rtl->pending, node))
-  {
-    rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
-    if (rtems_rtl_obj_has_symbol (obj, sym))
-      return obj;
-    node = rtems_chain_next (node);
+  if (sym != NULL)
+  {
+    rtems_chain_node* node = rtems_chain_first (&rtl->objects);
+    while (!rtems_chain_is_tail (&rtl->objects, node))
+    {
+      rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+      if (rtems_rtl_obj_has_symbol (obj, sym))
+        return obj;
+      node = rtems_chain_next (node);
+    }
+    node = rtems_chain_first (&rtl->pending);
+    while (!rtems_chain_is_tail (&rtl->pending, node))
+    {
+      rtems_rtl_obj* obj = (rtems_rtl_obj*) node;
+      if (rtems_rtl_obj_has_symbol (obj, sym))
+        return obj;
+      node = rtems_chain_next (node);
+    }
   }
   return NULL;
Index: testsuites/libtests/dl08/init.c
===================================================================
--- testsuites/libtests/dl08/init.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ testsuites/libtests/dl08/init.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -57,5 +57,5 @@
   }
 
-  for (i = 0; i < 100; ++i)
+  for (i = 0; i < 4; ++i)
   {
     printf ("--------------------------------------------------\n");
Index: testsuites/libtests/dl09/dl-o1.c
===================================================================
--- testsuites/libtests/dl09/dl-o1.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ testsuites/libtests/dl09/dl-o1.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -56,4 +56,5 @@
   printf (DL_NAME ":       dl01_const2: %4zu: %p: %f\n",   PAINT_VAR (dl01_const2));
   printf (DL_NAME ":        dl01_func1: %4zu: %p\n",       sizeof(dl01_func1), &dl01_func1);
+  printf (DL_NAME ":     rtems_main_o2:       %p\n",       &rtems_main_o2);
 
   rtems_main_o2 ();
Index: testsuites/libtests/dl09/init.c
===================================================================
--- testsuites/libtests/dl09/init.c	(revision be50969881b97180bf4fc1e2975efd41169e08bb)
+++ testsuites/libtests/dl09/init.c	(revision b36c52097f52012f9a52dff6fc8393d63805158b)
@@ -57,5 +57,5 @@
   }
 
-  for (i = 0; i < 100; ++i)
+  for (i = 0; i < 4; ++i)
   {
     printf ("--------------------------------------------------\n");
