[rtems commit] libdl: Add support for large memory programs

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


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

Author:    Chris Johns <chrisj at rtems.org>
Date:      Tue Jan 22 08:48:19 2019 +1100

libdl: Add support for large memory programs

- Add trampolines to support relocs that are out of range on
  support architectures.

- Support not loading separate text/data sections in an object
  file if the symbol provided in the section is a duplicate.
  A base image may have pulled in part of an object and another
  part needs to be dynamically loaded.

- Refactor the unresolved handling to scale to hundreds of
  unresolved symbols when loading large number of files.

Updates #3685

---

 cpukit/include/rtems/rtl/rtl-obj.h        |  30 ++-
 cpukit/include/rtems/rtl/rtl-trace.h      |   7 +-
 cpukit/include/rtems/rtl/rtl-unresolved.h |  13 +-
 cpukit/include/rtems/rtl/rtl.h            |   9 +
 cpukit/libdl/rtl-archive.c                | 125 +++++-----
 cpukit/libdl/rtl-elf.c                    | 349 +++++++++++++++++----------
 cpukit/libdl/rtl-mdreloc-arm.c            |  36 ++-
 cpukit/libdl/rtl-mdreloc-i386.c           |   9 +-
 cpukit/libdl/rtl-obj.c                    |  88 ++++---
 cpukit/libdl/rtl-shell.c                  |  17 +-
 cpukit/libdl/rtl-unresolved.c             | 388 +++++++++++++++++-------------
 cpukit/libdl/rtl.c                        |  10 +-
 testsuites/libtests/Makefile.am           |  15 +-
 testsuites/libtests/dl08/dl-load.c        |   4 +-
 testsuites/libtests/dl09/dl-load.c        |  10 +-
 testsuites/libtests/dl09/dl-o5.c          |   1 +
 16 files changed, 669 insertions(+), 442 deletions(-)

diff --git a/cpukit/include/rtems/rtl/rtl-obj.h b/cpukit/include/rtems/rtl/rtl-obj.h
index 4ce3560..e01af20 100644
--- a/cpukit/include/rtems/rtl/rtl-obj.h
+++ b/cpukit/include/rtems/rtl/rtl-obj.h
@@ -92,19 +92,20 @@ typedef struct rtems_rtl_loader_table
 #define RTEMS_RTL_OBJ_SECT_DATA  (1 << 2)  /**< Section holds program data. */
 #define RTEMS_RTL_OBJ_SECT_BSS   (1 << 3)  /**< Section holds program bss. */
 #define RTEMS_RTL_OBJ_SECT_EH    (1 << 4)  /**< Section holds exception data. */
-#define RTEMS_RTL_OBJ_SECT_REL   (1 << 5)  /**< Section holds relocation recs. */
-#define RTEMS_RTL_OBJ_SECT_RELA  (1 << 6)  /**< Section holds reloc addend recs. */
-#define RTEMS_RTL_OBJ_SECT_SYM   (1 << 7)  /**< Section holds symbols. */
-#define RTEMS_RTL_OBJ_SECT_STR   (1 << 8)  /**< Section holds strings. */
-#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 9)  /**< Section allocates runtime memory. */
-#define RTEMS_RTL_OBJ_SECT_LOAD  (1 << 10) /**< Section is loaded from object file. */
-#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 11) /**< Section is writable, ie data. */
-#define RTEMS_RTL_OBJ_SECT_EXEC  (1 << 12) /**< Section is executable. */
-#define RTEMS_RTL_OBJ_SECT_ZERO  (1 << 13) /**< Section is preset to zero. */
-#define RTEMS_RTL_OBJ_SECT_LINK  (1 << 14) /**< Section is link-ordered. */
-#define RTEMS_RTL_OBJ_SECT_CTOR  (1 << 15) /**< Section contains constructors. */
-#define RTEMS_RTL_OBJ_SECT_DTOR  (1 << 16) /**< Section contains destructors. */
-#define RTEMS_RTL_OBJ_SECT_LOCD  (1 << 17) /**< Section has been located. */
+#define RTEMS_RTL_OBJ_SECT_TLS   (1 << 5)  /**< Section holds TLS data. */
+#define RTEMS_RTL_OBJ_SECT_REL   (1 << 6)  /**< Section holds relocation recs. */
+#define RTEMS_RTL_OBJ_SECT_RELA  (1 << 7)  /**< Section holds reloc addend recs. */
+#define RTEMS_RTL_OBJ_SECT_SYM   (1 << 8)  /**< Section holds symbols. */
+#define RTEMS_RTL_OBJ_SECT_STR   (1 << 9)  /**< Section holds strings. */
+#define RTEMS_RTL_OBJ_SECT_ALLOC (1 << 10  /**< Section allocates runtime memory. */
+#define RTEMS_RTL_OBJ_SECT_LOAD  (1 << 11) /**< Section is loaded from object file. */
+#define RTEMS_RTL_OBJ_SECT_WRITE (1 << 12) /**< Section is writable, ie data. */
+#define RTEMS_RTL_OBJ_SECT_EXEC  (1 << 13) /**< Section is executable. */
+#define RTEMS_RTL_OBJ_SECT_ZERO  (1 << 14) /**< Section is preset to zero. */
+#define RTEMS_RTL_OBJ_SECT_LINK  (1 << 15) /**< Section is link-ordered. */
+#define RTEMS_RTL_OBJ_SECT_CTOR  (1 << 16) /**< Section contains constructors. */
+#define RTEMS_RTL_OBJ_SECT_DTOR  (1 << 17) /**< Section contains destructors. */
+#define RTEMS_RTL_OBJ_SECT_LOCD  (1 << 18) /**< Section has been located. */
 
 /**
  * Section types mask.
@@ -113,6 +114,7 @@ typedef struct rtems_rtl_loader_table
                                   RTEMS_RTL_OBJ_SECT_CONST | \
                                   RTEMS_RTL_OBJ_SECT_DATA | \
                                   RTEMS_RTL_OBJ_SECT_BSS | \
+                                  RTEMS_RTL_OBJ_SECT_TLS | \
                                   RTEMS_RTL_OBJ_SECT_EH)
 
 /**
@@ -204,11 +206,13 @@ struct rtems_rtl_obj
   size_t              text_size;    /**< The size of the text section. */
   void*               const_base;   /**< The base address of the const section
                                      *   in memory. */
+  size_t              const_size;    /**< The size of the const section. */
   void*               eh_base;      /**< The base address of the eh section in
                                      *   memory. */
   size_t              eh_size;      /**< The size of the eh section. */
   void*               data_base;    /**< The base address of the data section
                                      *   in memory. */
+  size_t              data_size;    /**< The size of the data section. */
   void*               bss_base;     /**< The base address of the bss section in
                                      *   memory. */
   size_t              bss_size;     /**< The size of the bss section. */
diff --git a/cpukit/include/rtems/rtl/rtl-trace.h b/cpukit/include/rtems/rtl/rtl-trace.h
index 84e81d5..6905e02 100644
--- a/cpukit/include/rtems/rtl/rtl-trace.h
+++ b/cpukit/include/rtems/rtl/rtl-trace.h
@@ -49,8 +49,11 @@ typedef uint32_t rtems_rtl_trace_mask;
 #define RTEMS_RTL_TRACE_UNRESOLVED             (1UL << 10)
 #define RTEMS_RTL_TRACE_CACHE                  (1UL << 11)
 #define RTEMS_RTL_TRACE_ARCHIVES               (1UL << 12)
-#define RTEMS_RTL_TRACE_DEPENDENCY             (1UL << 13)
-#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE))
+#define RTEMS_RTL_TRACE_ARCHIVE_SYMS           (1UL << 13)
+#define RTEMS_RTL_TRACE_DEPENDENCY             (1UL << 14)
+#define RTEMS_RTL_TRACE_ALL                    (0xffffffffUL & ~(RTEMS_RTL_TRACE_CACHE | \
+                                                                 RTEMS_RTL_TRACE_GLOBAL_SYM | \
+                                                                 RTEMS_RTL_TRACE_ARCHIVE_SYMS))
 
 /**
  * Call to check if this part is bring traced. If RTEMS_RTL_TRACE is defined to
diff --git a/cpukit/include/rtems/rtl/rtl-unresolved.h b/cpukit/include/rtems/rtl/rtl-unresolved.h
index a425384..efc9ce2 100644
--- a/cpukit/include/rtems/rtl/rtl-unresolved.h
+++ b/cpukit/include/rtems/rtl/rtl-unresolved.h
@@ -53,6 +53,7 @@
 #define _RTEMS_RTL_UNRESOLVED_H_
 
 #include <rtems.h>
+#include <rtems/chain.h>
 #include "rtl-obj-fwd.h"
 
 #ifdef __cplusplus
@@ -79,6 +80,8 @@ typedef enum rtems_rtl_unresolved_rtype
  * Unresolved external symbol flags.
  */
 #define RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE (1 << 0) /**< Search the archive. */
+#define RTEMS_RTL_UNRESOLV_SYM_HAS_ERROR      (1 << 1) /**< The symbol load
+                                                        *   has an error. */
 
 /**
  * Unresolved externals symbols. The symbols are reference counted and separate
@@ -93,7 +96,7 @@ typedef struct rtems_rtl_unresolv_symbol
   uint16_t   refs;     /**< The number of references to this name. */
   uint16_t   flags;    /**< Flags to manage the symbol. */
   uint16_t   length;   /**< The length of this name. */
-  const char name[10]; /**< The symbol name. */
+  const char name[];   /**< The symbol name. */
 } rtems_rtl_unresolv_symbol;
 
 /**
@@ -117,7 +120,7 @@ typedef struct rtems_rtl_unresolv_rec
   rtems_rtl_unresolved_rtype type;
   union
   {
-    rtems_rtl_unresolv_symbol name;   /**< The symnbol, or */
+    rtems_rtl_unresolv_symbol name;   /**< The symbol, or */
     rtems_rtl_unresolv_reloc  reloc;  /**< the relocation record. */
   } rec;
 } rtems_rtl_unresolv_rec;
@@ -127,9 +130,9 @@ typedef struct rtems_rtl_unresolv_rec
  */
 typedef struct rtems_rtl_unresolv_block
 {
-  rtems_chain_node       link; /**< Blocks are chained. */
-  uint32_t               recs; /**< The number of records in the block. */
-  rtems_rtl_unresolv_rec rec;  /**< The records. More follow. */
+  rtems_chain_node       link;  /**< Blocks are chained. */
+  uint32_t               recs;  /**< The number of records in the block. */
+  rtems_rtl_unresolv_rec rec[]; /**< The records. More follow. */
 } rtems_rtl_unresolv_block;
 
 /**
diff --git a/cpukit/include/rtems/rtl/rtl.h b/cpukit/include/rtems/rtl/rtl.h
index debf17c..044aa2a 100644
--- a/cpukit/include/rtems/rtl/rtl.h
+++ b/cpukit/include/rtems/rtl/rtl.h
@@ -138,6 +138,15 @@ rtems_rtl_data* rtems_rtl_data_unprotected (void);
 rtems_rtl_symbols* rtems_rtl_global_symbols (void);
 
 /**
+ * Get the RTL last error string with out locking. This call assumes the RTL is
+ * locked.
+ *
+ * @return const char* The RTL's laste error.
+ * @retval NULL The RTL data is not initialised.
+ */
+const char* rtems_rtl_last_error_unprotected (void);
+
+/**
  * Get the RTL objects table with out locking. This call assumes the RTL
  * is locked.
  *
diff --git a/cpukit/libdl/rtl-archive.c b/cpukit/libdl/rtl-archive.c
index 786c9c6..be1199f 100644
--- a/cpukit/libdl/rtl-archive.c
+++ b/cpukit/libdl/rtl-archive.c
@@ -293,32 +293,22 @@ rtems_rtl_archive_obj_finder (rtems_rtl_archive* archive, void* data)
     }
     else
     {
-      ssize_t entry = symbols->entries / 2;
-      ssize_t offset = entry;
-      ssize_t last_entry = -1;
-      while (entry >= 0 &&
-             entry < symbols->entries &&
-             entry != last_entry &&
-             offset > 0)
+      rtems_rtl_archive_symbol*      match;
+      const rtems_rtl_archive_symbol key = {
+        .entry = -1,
+        .label = search->symbol
+      };
+      match = bsearch (&key,
+                       symbols->symbols,
+                       symbols->entries,
+                       sizeof (symbols->symbols[0]),
+                       rtems_rtl_archive_symbol_compare);
+      if (match != NULL)
       {
-        int cmp = strcmp (search->symbol, symbols->symbols[entry].label);
-        if (cmp == 0)
-        {
-          entry = symbols->symbols[entry].entry;
           search->archive = archive;
           search->offset =
-            rtems_rtl_archive_read_32 (symbols->base + (entry * 4));
+            rtems_rtl_archive_read_32 (symbols->base + (match->entry * 4));
           return false;
-        }
-        last_entry = entry;
-        if (offset == 1)
-          offset = 0;
-        else
-          offset = ((offset - 1) / 2) + 1;
-        if (cmp < 0)
-          entry -= offset;
-        else
-          entry += offset;
       }
     }
   }
@@ -452,7 +442,7 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
     rtems_rtl_alloc_del (RTEMS_RTL_ALLOC_OBJECT, (void*) archives->config);
     archives->config_length = 0;
     archives->config =
-      rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sb.st_size, false);
+      rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_OBJECT, sb.st_size + 1, true);
     if (archives->config == NULL)
     {
       if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
@@ -519,45 +509,29 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
      * Remove leading and trailing white space.
      */
     s = (char*) archives->config;
-    for (r = 0; r < archives->config_length; ++r)
+    r = 0;
+    while (r < archives->config_length)
     {
-      if (s[r] != '\0')
+      if (s[r] == '\0')
+      {
+        ++r;
+      }
+      else
       {
         size_t ls = strlen (&s[r]);
         size_t b = 0;
         while (b < ls && isspace (s[r + b]))
         {
+          s[r + b] = '\0';
           ++b;
         }
-        if (b > 0)
-          memmove (&s[r], &s[r + b], ls - b);
         b = ls - 1;
-        while (b > 0 && isspace (s[r + b]))
+        while (b > 0 && isspace (s[b]))
         {
-          s[r + b] = '\0';
+          s[b] = '\0';
           --b;
         }
-      }
-    }
-
-    /*
-     * Compact the lines so there is only a single nul separator.
-     */
-    s = (char*) archives->config;
-    for (r = 0; r < archives->config_length; ++r)
-    {
-      if (s[r] == '\0')
-      {
-        size_t e = r + 1;
-        while (e < archives->config_length)
-        {
-          if (s[e] != '\0')
-          {
-            if (archives->config_length - e - 1 > 0)
-              memmove (&s[r + 1], &s[e], archives->config_length - e - 1);
-            break;
-          }
-        }
+        r += ls;
       }
     }
 
@@ -565,13 +539,17 @@ rtems_rtl_archives_load_config (rtems_rtl_archives* archives)
     {
       int line = 1;
       printf ("rtl: archive: config:\n");
-      s = (char*) archives->config;
-      for (r = 0; r < archives->config_length; ++r, ++line)
+      r = 0;
+      while (r < archives->config_length)
       {
-        size_t len = strlen (s);
-        printf (" %3d: %s\n", line, s);
-        s += len + 2;
-        r += len;
+        const char* cs = &archives->config[r];
+        size_t      len = strlen (cs);
+        if (len > 0)
+        {
+          printf (" %3d: %s\n", line, cs);
+          ++line;
+        }
+        r += len + 1;
       }
     }
   }
@@ -740,6 +718,19 @@ rtems_rtl_archive_loader (rtems_rtl_archive* archive, void* data)
                 archive->symbols.names,
                 (archive->symbols.entries + 1) * 4,
                 archive->symbols.symbols);
+
+      if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVE_SYMS) &&
+          archive->symbols.entries > 0)
+      {
+        size_t e;
+        printf ("rtl: archive: symbols: %s\n", archive->name );
+        for (e = 0; e < archive->symbols.entries; ++e)
+        {
+          printf(" %6zu: %6zu %s\n", e + 1,
+                 archive->symbols.symbols[e].entry,
+                 archive->symbols.symbols[e].label);
+        }
+      }
     }
 
     close (fd);
@@ -851,19 +842,16 @@ rtems_rtl_archives_refresh (rtems_rtl_archives* archives)
           break;
 
         if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
-          printf ("rtl: archive: refresh: checking: %s\n", entry.d_name);
+          printf ("rtl: archive: refresh: checking: %s (pattern: %s)\n",
+                  entry.d_name, basename);
 
         if (fnmatch (basename, entry.d_name, 0) == 0)
         {
-          struct stat sb;
-          if (stat (entry.d_name, &sb) == 0)
-          {
-            rtems_rtl_archive* archive;
-            archive = rtems_rtl_archive_get (archives, dirname, entry.d_name);
-            if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
-              printf ("rtl: archive: refresh: %s: %sfound\n",
-                      entry.d_name, archive == NULL ? ": not " : "");
-          }
+          rtems_rtl_archive* archive;
+          archive = rtems_rtl_archive_get (archives, dirname, entry.d_name);
+          if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
+            printf ("rtl: archive: refresh: %s: %sfound\n",
+                    entry.d_name, archive == NULL ? ": not " : "");
         }
       }
       closedir (dir);
@@ -1028,8 +1016,9 @@ rtems_rtl_archive_obj_load (rtems_rtl_archives* archives,
   if (!rtems_rtl_obj_load (obj))
   {
     if (rtems_rtl_trace (RTEMS_RTL_TRACE_ARCHIVES))
-      printf ("rtl: archive: loading: error: %s:%s at 0x%08jx\n",
-              obj->aname, obj->oname, obj->ooffset);
+      printf ("rtl: archive: loading: error: %s:%s at 0x%08jx: %s\n",
+              obj->aname, obj->oname, obj->ooffset,
+              rtems_rtl_last_error_unprotected ());
     rtems_chain_extract (&obj->link);
     rtems_rtl_obj_free (obj);
     rtems_rtl_obj_caches_flush ();
diff --git a/cpukit/libdl/rtl-elf.c b/cpukit/libdl/rtl-elf.c
index 96af16c..e65c703 100644
--- a/cpukit/libdl/rtl-elf.c
+++ b/cpukit/libdl/rtl-elf.c
@@ -21,6 +21,7 @@
 
 #include <errno.h>
 #include <fcntl.h>
+#include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
 #include <stdio.h>
@@ -64,6 +65,31 @@ rtems_rtl_elf_machine_check (Elf_Ehdr* ehdr)
   return true;
 }
 
+static const char*
+rtems_rtl_elf_separated_section (const char* name)
+{
+  struct {
+    const char* label;
+    size_t      len;
+  } prefix[] = {
+    #define SEPARATED_PREFIX(_p) { _p, sizeof (_p) - 1 }
+    SEPARATED_PREFIX (".text."),
+    SEPARATED_PREFIX (".rel.text."),
+    SEPARATED_PREFIX (".data."),
+    SEPARATED_PREFIX (".rel.data."),
+    SEPARATED_PREFIX (".rodata."),
+    SEPARATED_PREFIX (".rel.rodata.")
+  };
+  const size_t prefixes = sizeof (prefix) / sizeof (prefix[0]);
+  size_t       p;
+  for (p = 0; p < prefixes; ++p)
+  {
+    if (strncmp (name, prefix[p].label, prefix[p].len) == 0)
+      return name + prefix[p].len;
+  }
+  return NULL;
+}
+
 static bool
 rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
                            const Elf_Sym*      sym,
@@ -100,6 +126,7 @@ rtems_rtl_elf_find_symbol (rtems_rtl_obj*      obj,
     return false;
 
   *value = sym->st_value + (Elf_Addr) sect->base;
+
   return true;
 }
 
@@ -141,62 +168,68 @@ rtems_rtl_elf_reloc_parser (rtems_rtl_obj*      obj,
   rtems_rtl_elf_reloc_data* rd = (rtems_rtl_elf_reloc_data*) data;
 
   /*
-   * Check the reloc record to see if a trampoline is needed.
-   */
-  if (is_rela)
-  {
-    const Elf_Rela* rela = (const Elf_Rela*) relbuf;
-    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-      printf ("rtl: rela tramp: sym:%s(%d)=%08jx type:%d off:%08jx addend:%d\n",
-              symname, (int) ELF_R_SYM (rela->r_info),
-              (uintmax_t) symvalue, (int) ELF_R_TYPE (rela->r_info),
-              (uintmax_t) rela->r_offset, (int) rela->r_addend);
-    if (!rtems_rtl_elf_relocate_rela_tramp (obj, rela, targetsect,
-                                            symname, sym->st_info, symvalue))
-      return false;
-  }
-  else
-  {
-    const Elf_Rel* rel = (const Elf_Rel*) relbuf;
-    if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
-      printf ("rtl: rel tramp: sym:%s(%d)=%08jx type:%d off:%08jx\n",
-              symname, (int) ELF_R_SYM (rel->r_info),
-              (uintmax_t) symvalue, (int) ELF_R_TYPE (rel->r_info),
-              (uintmax_t) rel->r_offset);
-    if (!rtems_rtl_elf_relocate_rel_tramp (obj, rel, targetsect,
-                                           symname, sym->st_info, symvalue))
-      return false;
-  }
-
-  /*
-   * If the symbol has been resolved and there is a symbol name it is a global
-   * symbol and from another object file so add it as a dependency.
+   * 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;
   }
-  else if (symname != NULL)
+  else
   {
     /*
-     * 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.
+     * Check the reloc record to see if a trampoline is needed.
      */
-    rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
-    if (sobj != NULL)
+    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)
     {
       /*
-       * A dependency is not the base kernel image or itself. Tag the object as
-       * having been visited so we count it only once.
+       * 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 (sobj != rtems_rtl_baseimage () && obj != sobj &&
-          (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
+      rtems_rtl_obj*  sobj = rtems_rtl_find_obj_with_symbol (symbol);
+      if (sobj != NULL)
       {
-        sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
-        ++rd->dependents;
+        /*
+         * A dependency is not the base kernel image or itself. Tag the object as
+         * having been visited so we count it only once.
+         */
+        if (sobj != rtems_rtl_baseimage () && obj != sobj &&
+            (sobj->flags & RTEMS_RTL_OBJ_RELOC_TAG) == 0)
+        {
+          sobj->flags |= RTEMS_RTL_OBJ_RELOC_TAG;
+          ++rd->dependents;
+        }
       }
     }
   }
+
   return true;
 }
 
@@ -313,6 +346,14 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
   if (!targetsect)
     return true;
 
+  /*
+   * The section muct has been loaded. It could be a separate section in an
+   * archive and not loaded.
+   */
+  if ((targetsect->flags & RTEMS_RTL_OBJ_SECT_LOAD) == 0)
+    return true;
+
+
   rtems_rtl_obj_caches (&symbols, &strings, &relocs);
 
   if (!symbols || !strings || !relocs)
@@ -379,6 +420,7 @@ rtems_rtl_elf_relocate_worker (rtems_rtl_obj*              obj,
      * Only need the name of the symbol if global or a common symbol.
      */
     if (ELF_ST_TYPE (sym.st_info) == STT_NOTYPE ||
+        ELF_ST_TYPE (sym.st_info) == STT_TLS ||
         sym.st_shndx == SHN_COMMON)
     {
       size_t len;
@@ -686,6 +728,12 @@ rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
               symbol.st_shndx,
               (int) symbol.st_size);
 
+            /*
+         * If a duplicate forget it.
+         */
+        if (rtems_rtl_symbol_global_find (name))
+          continue;
+
     if ((symbol.st_shndx != 0) &&
         ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
          (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
@@ -705,16 +753,24 @@ rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
         {
           /*
            * If there is a globally exported symbol already present and this
-           * symbol is not weak raise an error. If the symbol is weak and
-           * present globally ignore this symbol and use the global one and if
-           * it is not present take this symbol global or weak. We accept the
-           * first weak symbol we find and make it globally exported.
+           * symbol is not weak raise check if the object file being loaded is
+           * from an archive. If the base image is built with text sections a
+           * symbol with it's section will be linked into the base image and not
+           * another symbol. If not an archive rause an error.
+           *
+           * If the symbol is weak and present globally ignore this symbol and
+           * use the global one and if it is not present take this symbol global
+           * or weak. We accept the first weak symbol we find and make it
+           * globally exported.
            */
           if (rtems_rtl_symbol_global_find (name) &&
               (ELF_ST_BIND (symbol.st_info) != STB_WEAK))
           {
-            rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
-            return false;
+            if (!rtems_rtl_obj_aname_valid (obj))
+            {
+              rtems_rtl_set_error (ENOMEM, "duplicate global symbol: %s", name);
+              return false;
+            }
           }
           else
           {
@@ -784,10 +840,9 @@ rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
 
   for (sym = 0; sym < (sect->size / sizeof (Elf_Sym)); ++sym)
   {
-    Elf_Sym     symbol;
-    off_t       off;
-    const char* name;
-    size_t      len;
+    Elf_Sym symbol;
+    off_t   off;
+    size_t  len;
 
     off = obj->ooffset + sect->offset + (sym * sizeof (symbol));
 
@@ -811,12 +866,6 @@ rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
       return false;
     }
 
-    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 ((symbol.st_shndx != 0) &&
         ((ELF_ST_TYPE (symbol.st_info) == STT_OBJECT) ||
          (ELF_ST_TYPE (symbol.st_info) == STT_COMMON) ||
@@ -825,62 +874,76 @@ rtems_rtl_elf_symbols (rtems_rtl_obj*      obj,
          ((ELF_ST_BIND (symbol.st_info) == STB_GLOBAL) ||
           (ELF_ST_BIND (symbol.st_info) == STB_WEAK) ||
           (ELF_ST_BIND (symbol.st_info) == STB_LOCAL)))
+    {
+      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);
+      if (symsect)
       {
-        rtems_rtl_obj_sect* symsect;
-        rtems_rtl_obj_sym*  osym;
-        char*               string;
-        Elf_Word            value;
+        const char* name;
 
-        symsect = rtems_rtl_obj_find_section_by_index (obj, symbol.st_shndx);
-        if (symsect)
-        {
-          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;
-          }
+        off = obj->ooffset + strtab->offset + symbol.st_name;
+        len = RTEMS_RTL_ELF_STRING_MAX;
 
-          /*
-           * 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;
-          }
+        if (!rtems_rtl_obj_cache_read (strings, fd, off, (void**) &name, &len))
+          return false;
 
-          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;
+        /*
+         * If a duplicate forget it.
+         */
+        if (rtems_rtl_symbol_global_find (name))
+          continue;
 
-          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 ((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;
+
+        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)
@@ -955,6 +1018,8 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
 
   for (section = 0; section < ehdr->e_shnum; ++section)
   {
+    char*    name;
+    size_t   len;
     uint32_t flags;
 
     /*
@@ -968,9 +1033,15 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
     if (!rtems_rtl_obj_cache_read_byval (sects, fd, off, &shdr, sizeof (shdr)))
       return false;
 
+    len = RTEMS_RTL_ELF_STRING_MAX;
+    if (!rtems_rtl_obj_cache_read (strings, fd,
+                                   sectstroff + shdr.sh_name,
+                                   (void**) &name, &len))
+      return false;
+
     if (rtems_rtl_trace (RTEMS_RTL_TRACE_DETAIL))
-      printf ("rtl: section: %2d: type=%d flags=%08x link=%d info=%d\n",
-              section, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
+      printf ("rtl: section: %2d: name=%s type=%d flags=%08x link=%d info=%d\n",
+              section, name, (int) shdr.sh_type, (unsigned int) shdr.sh_flags,
               (int) shdr.sh_link, (int) shdr.sh_info);
 
     flags = 0;
@@ -1010,7 +1081,7 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
         break;
 
       case SHT_RELA:
-        flags = RTEMS_RTL_OBJ_SECT_RELA;
+        flags = RTEMS_RTL_OBJ_SECT_RELA | RTEMS_RTL_OBJ_SECT_LOAD;
         break;
 
       case SHT_REL:
@@ -1018,7 +1089,7 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
          * The sh_link holds the section index for the symbol table. The sh_info
          * holds the section index the relocations apply to.
          */
-        flags = RTEMS_RTL_OBJ_SECT_REL;
+        flags = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_LOAD;
         break;
 
       case SHT_SYMTAB:
@@ -1063,8 +1134,18 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
 
     if (flags != 0)
     {
-      char*  name;
-      size_t len;
+      /*
+       * If the object file is part of a library check the section's name. If it
+       * starts with '.text.*' see if the last part is a global symbol. If a
+       * global symbol exists we have to assume the symbol in the archive is a
+       * duplicate can can be ignored.
+       */
+      if (rtems_rtl_obj_aname_valid (obj))
+      {
+        const char* symname = rtems_rtl_elf_separated_section (name);
+        if (symname != NULL && rtems_rtl_symbol_global_find (symname))
+          flags &= ~RTEMS_RTL_OBJ_SECT_LOAD;
+      }
 
       /*
        * If link ordering this section must appear in the same order in memory
@@ -1074,14 +1155,8 @@ rtems_rtl_elf_parse_sections (rtems_rtl_obj* obj, int fd, Elf_Ehdr* ehdr)
         flags |= RTEMS_RTL_OBJ_SECT_LINK;
 
       /*
-       * Some architexctures support a named PROGBIT section for INIT/FINI.
+       * Some architexctures have a named PROGBIT section for INIT/FINI.
        */
-      len = RTEMS_RTL_ELF_STRING_MAX;
-      if (!rtems_rtl_obj_cache_read (strings, fd,
-                                     sectstroff + shdr.sh_name,
-                                     (void**) &name, &len))
-        return false;
-
       if (strcmp (".ctors", name) == 0)
         flags |= RTEMS_RTL_OBJ_SECT_CTOR;
       if (strcmp (".dtors", name) == 0)
@@ -1153,25 +1228,34 @@ rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
 {
   rtems_chain_control* sections = NULL;
   rtems_chain_node*    node = NULL;
-  size_t               mask = 0;
   int                  sec_num = 0;
   section_detail*      sd;
   int                  i = 0;
+  size_t               m;
 
   /*
-   * Caculate the size of sections' name.
+   * The section masks to add to the linkmap.
    */
+  const uint32_t       sect_mask[] = {
+    RTEMS_RTL_OBJ_SECT_TEXT | RTEMS_RTL_OBJ_SECT_LOAD,
+    RTEMS_RTL_OBJ_SECT_CONST | RTEMS_RTL_OBJ_SECT_LOAD,
+    RTEMS_RTL_OBJ_SECT_DATA | RTEMS_RTL_OBJ_SECT_LOAD,
+    RTEMS_RTL_OBJ_SECT_BSS
+  };
+  const size_t sect_masks = sizeof (sect_mask) / sizeof (sect_mask[0]);
 
-  for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
-       mask <= RTEMS_RTL_OBJ_SECT_BSS;
-       mask <<= 1)
+  /*
+   * Caculate the size of sections' name.
+   */
+  for (m = 0; m < sect_masks; ++m)
   {
     sections = &obj->sections;
     node = rtems_chain_first (sections);
     while (!rtems_chain_is_tail (sections, node))
     {
       rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
-      if ((sect->size != 0) && ((sect->flags & mask) != 0))
+      const uint32_t      mask = sect_mask[m];
+      if ((sect->size != 0) && ((sect->flags & mask) == mask))
       {
         ++sec_num;
       }
@@ -1205,36 +1289,35 @@ rtems_rtl_elf_load_linkmap (rtems_rtl_obj* obj)
   sections = &obj->sections;
   node = rtems_chain_first (sections);
 
-  for (mask = RTEMS_RTL_OBJ_SECT_TEXT;
-       mask <= RTEMS_RTL_OBJ_SECT_BSS;
-       mask <<= 1)
+  for (m = 0; m < sect_masks; ++m)
   {
     sections = &obj->sections;
     node = rtems_chain_first (sections);
     while (!rtems_chain_is_tail (sections, node))
     {
       rtems_rtl_obj_sect* sect = (rtems_rtl_obj_sect*) node;
+      const uint32_t      mask = sect_mask[m];
 
-      if ((sect->size != 0) && ((sect->flags & mask) != 0))
+      if ((sect->size != 0) && ((sect->flags & mask) == mask))
       {
         sd[i].name = sect->name;
         sd[i].size = sect->size;
-        if (mask == RTEMS_RTL_OBJ_SECT_TEXT)
+        if ((mask & RTEMS_RTL_OBJ_SECT_TEXT) != 0)
         {
           sd[i].rap_id = rap_text;
           sd[i].offset = sect->base - obj->text_base;
         }
-        if (mask == RTEMS_RTL_OBJ_SECT_CONST)
+        if ((mask & RTEMS_RTL_OBJ_SECT_CONST) != 0)
         {
           sd[i].rap_id = rap_const;
           sd[i].offset = sect->base - obj->const_base;
         }
-        if (mask == RTEMS_RTL_OBJ_SECT_DATA)
+        if ((mask & RTEMS_RTL_OBJ_SECT_DATA) != 0)
         {
           sd[i].rap_id = rap_data;
           sd[i].offset = sect->base - obj->data_base;
         }
-        if (mask == RTEMS_RTL_OBJ_SECT_BSS)
+        if ((mask & RTEMS_RTL_OBJ_SECT_BSS) != 0)
         {
           sd[i].rap_id = rap_bss;
           sd[i].offset = sect->base - obj->bss_base;
diff --git a/cpukit/libdl/rtl-mdreloc-arm.c b/cpukit/libdl/rtl-mdreloc-arm.c
index a00f0f8..19a5904 100644
--- a/cpukit/libdl/rtl-mdreloc-arm.c
+++ b/cpukit/libdl/rtl-mdreloc-arm.c
@@ -22,6 +22,12 @@
 #include "rtl-unwind.h"
 
 /*
+ * Set to 1 to allow untested relocations. If you tested one and it
+ * works or you fixed the relocation please remove the guard.
+ */
+#define ALLOW_UNTESTED_RELOCS 1
+
+/*
  * It is possible for the compiler to emit relocations for unaligned data.
  * We handle this situation with these inlines.
  */
@@ -341,8 +347,10 @@ rtems_rtl_elf_relor_rel (rtems_rtl_obj*            obj,
       else {
         if (ELF_R_TYPE(rel->r_info) == R_TYPE(THM_JUMP24)) {
           tmp = (tmp + 2) & ~3; /* aligned to 4 bytes only for JUMP24 */
+#if !ALLOW_UNTESTED_RELOCS
           printf("THM_JUMP24 to arm not supported\n");
           return false;
+#endif
         }
         else {
           /* THM_CALL bl-->blx */
@@ -440,11 +448,33 @@ rtems_rtl_elf_relor_rel (rtems_rtl_obj*            obj,
                 (void *)*where, where, rtems_rtl_obj_oname (obj));
       break;
 
+    case R_TYPE(TLS_LE32):
+#if ALLOW_UNTESTED_RELOCS
+      if (!parsing) {
+        addend = *where;
+        *where = symvalue + addend;
+        if (rtems_rtl_trace (RTEMS_RTL_TRACE_RELOC))
+          printf ("rtl: TLS_LE32 %p @ %p in %s\n",
+                  (void *)*where, where, rtems_rtl_obj_oname (obj));
+      }
+      break;
+#endif
+    case R_TYPE(TLS_GD32):
+    case R_TYPE(TLS_LDM32):
+    case R_TYPE(TLS_LDO32):
+    case R_TYPE(TLS_IE32):
+    case R_TYPE(TLS_LDO12):
+    case R_TYPE(TLS_LE12):
+    case R_TYPE(TLS_IE12GP):
+      printf("TSL relocations not supported\n");
+
     default:
-      printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p, "
-              "contents = %p\n",
+      printf ("rtl: reloc unknown: sym = %" PRIu32 ", type = %" PRIu32 ", offset = %p",
               ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
-              (void *)rel->r_offset, (void *)*where);
+                (void *)rel->r_offset);
+      if (!parsing)
+        printf("contents = %p", (void *)*where);
+      printf("\n");
       rtems_rtl_set_error (EINVAL,
                            "%s: Unsupported relocation type %" PRIu32 " "
                            "in non-PLT relocations",
diff --git a/cpukit/libdl/rtl-mdreloc-i386.c b/cpukit/libdl/rtl-mdreloc-i386.c
index 773ef8e..016f99f 100644
--- a/cpukit/libdl/rtl-mdreloc-i386.c
+++ b/cpukit/libdl/rtl-mdreloc-i386.c
@@ -7,6 +7,7 @@
 #include <sys/cdefs.h>
 
 #include <errno.h>
+#include <inttypes.h>
 #include <stdio.h>
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -67,7 +68,7 @@ rtems_rtl_elf_relocate_rela (rtems_rtl_obj*            obj,
                              const Elf_Word            symvalue)
 {
   (void) obj;
-  (void) rela;
+  (void) rel;
   (void) sect;
   (void) symname;
   (void) syminfo;
@@ -147,12 +148,12 @@ rtems_rtl_elf_relocate_rel (rtems_rtl_obj*            obj,
       break;
 
     default:
-      printf ("rtl: reloc unknown: sym = %lu, type = %lu, offset = %p, "
+      printf ("rtl: reloc unknown: sym = %i, type = %" PRIu32 ", offset = %p, "
               "contents = %p\n",
-              ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
+              (int) ELF_R_SYM(rel->r_info), (uint32_t) ELF_R_TYPE(rel->r_info),
               (void *)rel->r_offset, (void *)*where);
       rtems_rtl_set_error (EINVAL,
-                           "%s: Unsupported relocation type %ld "
+                           "%s: Unsupported relocation type %" PRIu32 " "
                            "in non-PLT relocations",
                            sect->name, (uint32_t) ELF_R_TYPE(rel->r_info));
       return false;
diff --git a/cpukit/libdl/rtl-obj.c b/cpukit/libdl/rtl-obj.c
index 6f1f2e4..0a7763b 100644
--- a/cpukit/libdl/rtl-obj.c
+++ b/cpukit/libdl/rtl-obj.c
@@ -158,6 +158,16 @@ rtems_rtl_obj_unresolved_dependent (rtems_rtl_obj* obj,
   return ud->has_unresolved;
 }
 
+static bool
+rtems_rtl_obj_unresolved_object (rtems_chain_node* node, void* data)
+{
+  rtems_rtl_obj*                 obj = (rtems_rtl_obj*) node;
+  rtems_rtl_obj_unresolved_data* ud;
+  ud = (rtems_rtl_obj_unresolved_data*) data;
+  ud->has_unresolved = (obj->flags & RTEMS_RTL_OBJ_UNRESOLVED) != 0;
+  return !ud->has_unresolved;
+}
+
 bool
 rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
 {
@@ -169,12 +179,22 @@ rtems_rtl_obj_unresolved (rtems_rtl_obj* obj)
             obj->oname, ud.has_unresolved ? "unresolved" : "resolved");
   if (!ud.has_unresolved)
   {
-    rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
-    obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
-    rtems_rtl_obj_iterate_dependents (obj,
-                                      rtems_rtl_obj_unresolved_dependent,
-                                      &ud);
-    rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
+    if ((obj->flags & RTEMS_RTL_OBJ_BASE) != 0)
+    {
+      rtems_rtl_data* rtl = rtems_rtl_data_unprotected ();
+      rtems_rtl_chain_iterate (&rtl->objects,
+                               rtems_rtl_obj_unresolved_object,
+                               &ud);
+    }
+    else
+    {
+      rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
+      obj->flags |= RTEMS_RTL_OBJ_DEP_VISITED;
+      rtems_rtl_obj_iterate_dependents (obj,
+                                        rtems_rtl_obj_unresolved_dependent,
+                                        &ud);
+      rtems_rtl_obj_update_flags (RTEMS_RTL_OBJ_DEP_VISITED, 0);
+    }
   }
   return ud.has_unresolved;
 }
@@ -727,49 +747,57 @@ rtems_rtl_obj_iterate_dependents (rtems_rtl_obj*                 obj,
 size_t
 rtems_rtl_obj_text_size (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_TEXT);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
+  return rtems_rtl_obj_section_size (obj, flags);
 }
 
 uint32_t
 rtems_rtl_obj_text_alignment (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_TEXT);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_TEXT;
+  return rtems_rtl_obj_section_alignment (obj, flags);
 }
 
 size_t
 rtems_rtl_obj_const_size (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_CONST);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
+  return rtems_rtl_obj_section_size (obj, flags);
 }
 
 uint32_t
-rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
+rtems_rtl_obj_const_alignment (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_EH);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_CONST;
+  return rtems_rtl_obj_section_alignment (obj, flags);
 }
 
-size_t
-rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
+uint32_t
+rtems_rtl_obj_eh_alignment (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_EH);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
+  return rtems_rtl_obj_section_alignment (obj, flags);
 }
 
-uint32_t
-rtems_rtl_obj_const_alignment (const rtems_rtl_obj* obj)
+size_t
+rtems_rtl_obj_eh_size (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_CONST);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_EH;
+  return rtems_rtl_obj_section_size (obj, flags);
 }
 
 size_t
 rtems_rtl_obj_data_size (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_size (obj, RTEMS_RTL_OBJ_SECT_DATA);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
+  return rtems_rtl_obj_section_size (obj, flags);
 }
 
 uint32_t
 rtems_rtl_obj_data_alignment (const rtems_rtl_obj* obj)
 {
-  return rtems_rtl_obj_section_alignment (obj, RTEMS_RTL_OBJ_SECT_DATA);
+  const uint32_t flags = RTEMS_RTL_OBJ_SECT_LOAD | RTEMS_RTL_OBJ_SECT_DATA;
+  return rtems_rtl_obj_section_alignment (obj, flags);
 }
 
 size_t
@@ -790,8 +818,10 @@ rtems_rtl_obj_relocate (rtems_rtl_obj*             obj,
                         rtems_rtl_obj_sect_handler handler,
                         void*                      data)
 {
-  uint32_t mask = RTEMS_RTL_OBJ_SECT_REL | RTEMS_RTL_OBJ_SECT_RELA;
-  return rtems_rtl_obj_section_handler (mask, obj, fd, handler, data);
+  const uint32_t flags = (RTEMS_RTL_OBJ_SECT_LOAD |
+                          RTEMS_RTL_OBJ_SECT_REL |
+                          RTEMS_RTL_OBJ_SECT_RELA);
+  return rtems_rtl_obj_section_handler (flags, obj, fd, handler, data);
 }
 
 /**
@@ -1012,12 +1042,14 @@ rtems_rtl_obj_sections_loader (uint32_t                   mask,
         }
         else
         {
+          /*
+           * This section is not to be loaded, clear the base.
+           */
           sect->base = 0;
-          rtems_rtl_set_error (errno, "section has no load/clear op");
-          return false;
         }
 
-        base_offset += sect->size;
+        if (sect->base)
+          base_offset += sect->size;
 
         ++order;
 
@@ -1053,9 +1085,11 @@ rtems_rtl_obj_load_sections (rtems_rtl_obj*             obj,
   /*
    * Set the sizes held in the object data. We need this for a fast reference.
    */
-  obj->text_size = text_size;
-  obj->eh_size   = eh_size;
-  obj->bss_size  = bss_size;
+  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;
 
   /*
    * Let the allocator manage the actual allocation. The user can use the
diff --git a/cpukit/libdl/rtl-shell.c b/cpukit/libdl/rtl-shell.c
index c2a1af5..ab55531 100644
--- a/cpukit/libdl/rtl-shell.c
+++ b/cpukit/libdl/rtl-shell.c
@@ -129,17 +129,6 @@ typedef struct
 } rtems_rtl_obj_print;
 
 /**
- * Return the different between 2 void*.
- */
-static size_t
-rtems_rtl_delta_voids (void* higher, void* lower)
-{
-  char* ch = higher;
-  char* cl = lower;
-  return ch - cl;
-}
-
-/**
  * Parse an argument.
  */
 static bool
@@ -235,11 +224,11 @@ rtems_rtl_obj_printer (rtems_rtl_obj_print* print, rtems_rtl_obj* obj)
   {
     printf ("%-*cexec size     : %zi\n", print->indent, ' ', obj->exec_size);
     printf ("%-*ctext base     : %p (%zi)\n", print->indent, ' ',
-            obj->text_base, rtems_rtl_delta_voids (obj->const_base, obj->text_base));
+            obj->text_base, obj->text_size);
     printf ("%-*cconst base    : %p (%zi)\n", print->indent, ' ',
-            obj->const_base, rtems_rtl_delta_voids (obj->data_base, obj->const_base));
+            obj->const_base, obj->const_size);
     printf ("%-*cdata base     : %p (%zi)\n", print->indent, ' ',
-            obj->data_base, rtems_rtl_delta_voids (obj->bss_base, obj->data_base));
+            obj->data_base, obj->data_size);
     printf ("%-*cbss base      : %p (%zi)\n", print->indent, ' ',
             obj->bss_base, obj->bss_size);
   }
diff --git a/cpukit/libdl/rtl-unresolved.c b/cpukit/libdl/rtl-unresolved.c
index 7e2d920..0e70c5d 100644
--- a/cpukit/libdl/rtl-unresolved.c
+++ b/cpukit/libdl/rtl-unresolved.c
@@ -36,13 +36,13 @@ rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
    */
   size_t size =
     (sizeof(rtems_rtl_unresolv_block) +
-     (sizeof(rtems_rtl_unresolv_rec) * (unresolved->block_recs - 1)));
+     (sizeof(rtems_rtl_unresolv_rec) * unresolved->block_recs));
   rtems_rtl_unresolv_block* block =
     rtems_rtl_alloc_new (RTEMS_RTL_ALLOC_EXTERNAL, size, true);
   if (block)
   {
     if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
-      printf ("rtl: unresolv: block-alloc %p\n", block);
+      printf ("rtl: unresolv: block-alloc %p (%p)\n", block, block + size);
     rtems_chain_append (&unresolved->blocks, &block->link);
   }
   else
@@ -53,28 +53,31 @@ rtems_rtl_unresolved_block_alloc (rtems_rtl_unresolved* unresolved)
 static size_t
 rtems_rtl_unresolved_symbol_rec_count (size_t length)
 {
-  return ((length + sizeof(rtems_rtl_unresolv_symbol) - 1) /
-          sizeof(rtems_rtl_unresolv_symbol));
+  const size_t rec_size = sizeof(rtems_rtl_unresolv_rec);
+  const size_t rec_name_header = offsetof(rtems_rtl_unresolv_rec, rec.name.name);
+  /*
+   * Add on the nul and rmeove 1 to be inside a record.
+   */
+  return ((length + rec_name_header - 1) / rec_size) + 1;
 }
 
-
 static size_t
 rtems_rtl_unresolved_symbol_recs (const char* name)
 {
-  return rtems_rtl_unresolved_symbol_rec_count (strlen (name));
+  return rtems_rtl_unresolved_symbol_rec_count (strlen (name) + 1);
 }
 
 static int
 rtems_rtl_unresolved_rec_index (rtems_rtl_unresolv_block* block,
                                 rtems_rtl_unresolv_rec* rec)
 {
-  return (rec - &block->rec) / sizeof (rtems_rtl_unresolv_rec);
+  return rec - &block->rec[0];
 }
 
 static rtems_rtl_unresolv_rec*
 rtems_rtl_unresolved_rec_first (rtems_rtl_unresolv_block* block)
 {
-  return &block->rec;
+  return &block->rec[0];
 }
 
 static rtems_rtl_unresolv_rec*
@@ -83,6 +86,7 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
   switch (rec->type)
   {
     case rtems_rtl_unresolved_empty:
+    default:
       /*
        * Empty returns NULL. The end of the records in the block.
        */
@@ -99,9 +103,6 @@ rtems_rtl_unresolved_rec_next (rtems_rtl_unresolv_rec* rec)
     case rtems_rtl_unresolved_reloc:
       ++rec;
       break;
-
-    default:
-      break;
   }
 
   return rec;
@@ -111,50 +112,121 @@ static bool
 rtems_rtl_unresolved_rec_is_last (rtems_rtl_unresolv_block* block,
                                   rtems_rtl_unresolv_rec*   rec)
 {
-  int index = (rec - &block->rec) / sizeof (rec);
-  return !rec || (index >= block->recs) || (rec->type == rtems_rtl_unresolved_empty);
+  int index = rtems_rtl_unresolved_rec_index (block, rec);
+  return (rec == NULL ||
+          (index < 0) ||
+          (index >= block->recs) ||
+          (rec->type == rtems_rtl_unresolved_empty));
 }
 
 static rtems_rtl_unresolv_rec*
 rtems_rtl_unresolved_rec_first_free (rtems_rtl_unresolv_block* block)
 {
-  return &block->rec + block->recs;
+  return &block->rec[0] + block->recs;
 }
 
-static int
-rtems_rtl_unresolved_find_name (rtems_rtl_unresolved* unresolved,
-                                const char*           name,
-                                bool                  update_refcount)
+/**
+ * Name management iterator data.
+ */
+typedef struct
 {
-  size_t length = strlen (name) + 1;
-  int    index = 1;
+  const char*             name;   /**< The name being searched for. */
+  size_t                  length; /**< The length of the name. */
+  rtems_rtl_unresolv_rec* rec;    /**< The record being searched for. */
+  int                     index;  /**< The name's index. */
+  int                     offset; /**< The offset to move the index. */
+} rtl_unresolved_name_data;
 
-  rtems_chain_node* node = rtems_chain_first (&unresolved->blocks);
-  while (!rtems_chain_is_tail (&unresolved->blocks, node))
+static bool
+rtems_rtl_unresolved_find_name_iterator (rtems_rtl_unresolv_rec* rec,
+                                         void*                   data)
+{
+  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
+  if (rec->type == rtems_rtl_unresolved_symbol)
   {
-    rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
-    rtems_rtl_unresolv_rec* rec = rtems_rtl_unresolved_rec_first (block);
-
-    while (!rtems_rtl_unresolved_rec_is_last (block, rec))
+    if ((rec->rec.name.length == nd->length)
+        && (strcmp (rec->rec.name.name, nd->name) == 0))
     {
-      if (rec->type == rtems_rtl_unresolved_symbol)
-      {
-        if ((rec->rec.name.length == length)
-            && (strcmp (rec->rec.name.name, name) == 0))
-        {
-          if (update_refcount)
-            ++rec->rec.name.refs;
-          return index;
-        }
-        ++index;
-      }
-      rec = rtems_rtl_unresolved_rec_next (rec);
+      ++rec->rec.name.refs;
+      return true;
     }
+    ++nd->index;
+  }
+  return false;
+}
 
-    node = rtems_chain_next (node);
+static int
+rtems_rtl_unresolved_find_name (const char* name)
+{
+  rtl_unresolved_name_data nd = {
+    .name = name,
+    .length = strlen (name) + 1,
+    .rec = NULL,
+    .index = 1,
+    .offset = 0
+  };
+  if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_name_iterator,
+                                    &nd))
+    return nd.index;
+  return -1;
+}
+
+static bool
+rtems_rtl_unresolved_find_index_iterator (rtems_rtl_unresolv_rec* rec,
+                                          void*                   data)
+{
+  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
+  if (rec == nd->rec)
+    return true;
+  if (rec->type == rtems_rtl_unresolved_symbol)
+    ++nd->index;
+  return false;
+}
+
+static int
+rtems_rtl_unresolved_find_index (rtems_rtl_unresolv_rec* rec)
+{
+  rtl_unresolved_name_data nd = {
+    .name = NULL,
+    .length = 0,
+    .rec = rec,
+    .index = 1,
+    .offset = 0
+  };
+  if (rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_find_index_iterator,
+                                    &nd))
+    return nd.index;
+  return -1;
+}
+
+static bool
+rtems_rtl_unresolved_reindex_iterator (rtems_rtl_unresolv_rec* rec,
+                                       void*                   data)
+{
+  rtl_unresolved_name_data* nd = (rtl_unresolved_name_data*) data;
+  /*
+   * Reindexing only effects the reloc records.
+   */
+  if (rec->type == rtems_rtl_unresolved_reloc)
+  {
+    if (rec->rec.reloc.name >= nd->index)
+      rec->rec.reloc.name += nd->offset;
   }
+  return false;
+}
 
-  return 0 - index;
+static void
+rtems_rtl_unresolved_reindex_names (uint16_t index, int offset)
+{
+  rtl_unresolved_name_data nd = {
+    .name = NULL,
+    .length = 0,
+    .rec = NULL,
+    .index = index,
+    .offset = offset
+  };
+  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_reindex_iterator,
+                                &nd);
 }
 
 /**
@@ -184,29 +256,31 @@ rtems_rtl_unresolved_resolve_reloc (rtems_rtl_unresolv_rec* rec,
         printf ("rtl: unresolv: resolve reloc: %s\n",
                 rd->name_rec->rec.name.name);
 
-      rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym);
-
-      /*
-       * If all unresolved externals are resolved add the obj module
-       * to the pending queue. This will flush the object module's
-       * data from the cache and call it's constructors.
-       */
-      if (rec->rec.reloc.obj->unresolved == 0)
+      if (rtems_rtl_obj_relocate_unresolved (&rec->rec.reloc, rd->sym))
       {
-        pending = rtems_rtl_pending_unprotected ();
-        rtems_chain_extract (&rec->rec.reloc.obj->link);
-        rtems_chain_append (pending, &rec->rec.reloc.obj->link);
-      }
+        /*
+         * If all unresolved externals are resolved add the obj module
+         * to the pending queue. This will flush the object module's
+         * data from the cache and call it's constructors.
+         */
+        if (rec->rec.reloc.obj->unresolved == 0)
+        {
+          pending = rtems_rtl_pending_unprotected ();
+          rtems_chain_extract (&rec->rec.reloc.obj->link);
+          rtems_chain_append (pending, &rec->rec.reloc.obj->link);
+        }
 
-      /*
-       * Check Set the object pointer to NULL to indicate the record is not used
-       * anymore. Update the reference count of the name. The sweep after
-       * relocating will remove the reloc records with obj set to NULL and
-       * names with a reference count of 0.
-       */
-      rec->rec.reloc.obj = NULL;
-      if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
-        --rd->name_rec->rec.name.refs;
+        /*
+         * Set the object pointer to NULL to indicate the record is
+         * not used anymore. Update the reference count of the name so
+         * it can garbage collected if not referenced. The sweep after
+         * relocating will remove the reloc records with obj set to
+         * NULL and names with a reference count of 0.
+         */
+        rec->rec.reloc.obj = NULL;
+        if (rd->name_rec != NULL && rd->name_rec->rec.name.refs > 0)
+          --rd->name_rec->rec.name.refs;
+      }
     }
   }
   return false;
@@ -250,9 +324,9 @@ rtems_rtl_unresolved_resolve_iterator (rtems_rtl_unresolv_rec* rec,
  */
 typedef struct rtems_rtl_unresolved_archive_reloc_data
 {
-  uint16_t            name;     /**< Name index. */
-  bool                loaded;   /**< Object file loaded. */
-  rtems_rtl_archives* archives; /**< The archives to search. */
+  uint16_t                 name;     /**< Name index. */
+  rtems_rtl_archive_search result;   /**< The result of the load. */
+  rtems_rtl_archives*      archives; /**< The archives to search. */
 } rtems_rtl_unresolved_archive_reloc_data;
 
 static bool
@@ -268,17 +342,18 @@ rtems_rtl_unresolved_archive_iterator (rtems_rtl_unresolv_rec* rec,
 
     if ((rec->rec.name.flags & RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE) != 0)
     {
-      rtems_rtl_archive_search load;
+      rtems_rtl_archive_search result;
 
       if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
         printf ("rtl: unresolv: archive lookup: %d: %s\n",
                 ard->name, rec->rec.name.name);
 
-      load = rtems_rtl_archive_obj_load (ard->archives,
-                                         rec->rec.name.name, true);
-      if (load == rtems_rtl_archive_search_loaded)
+      result = rtems_rtl_archive_obj_load (ard->archives,
+                                           rec->rec.name.name, true);
+      if (result != rtems_rtl_archive_search_not_found)
       {
-        ard->loaded = true;
+        rec->rec.name.flags &= ~RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
+        ard->result = result;
         return true;
       }
     }
@@ -292,10 +367,26 @@ rtems_rtl_unresolved_archive_search_iterator (rtems_rtl_unresolv_rec* rec,
                                               void*                   data)
 {
   if (rec->type == rtems_rtl_unresolved_symbol)
-    rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
+    rec->rec.name.flags |= RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
   return false;
 }
 
+static rtems_rtl_unresolv_block*
+rtems_rtl_unresolved_alloc_recs (rtems_rtl_unresolved* unresolved,
+                                 size_t                count)
+{
+  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;
+
+    if (block->recs + count <= unresolved->block_recs)
+      return block;
+    node = rtems_chain_next (node);
+  }
+  return NULL;
+}
+
 static void
 rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
                                   rtems_rtl_unresolv_rec*   rec,
@@ -309,7 +400,7 @@ rtems_rtl_unresolved_clean_block (rtems_rtl_unresolv_block* block,
     memmove (rec, rec + count, bytes);
   block->recs -= count;
   bytes = count * sizeof (rtems_rtl_unresolv_rec);
-  memset (&block->rec + block->recs, 0, bytes);
+  memset (&block->rec[block->recs], 0, bytes);
 }
 
 static void
@@ -328,51 +419,19 @@ rtems_rtl_unresolved_compact (void)
     {
       rtems_rtl_unresolv_block* block = (rtems_rtl_unresolv_block*) node;
       rtems_rtl_unresolv_rec*   rec = rtems_rtl_unresolved_rec_first (block);
-
       while (!rtems_rtl_unresolved_rec_is_last (block, rec))
       {
         bool next_rec = true;
+
         if (rec->type == rtems_rtl_unresolved_symbol)
         {
           ++index;
           if (rec->rec.name.refs == 0)
           {
-            /*
-             * Iterate over the remaining reloc records and update the index.
-             */
-            rtems_chain_node*       reindex_node;
-            rtems_rtl_unresolv_rec* reindex_first;
-            size_t                  name_recs;
+            size_t name_recs;
             if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
               printf ("rtl: unresolv: remove name: %s\n", rec->rec.name.name);
-            reindex_node = node;
-            reindex_first = rtems_rtl_unresolved_rec_next (rec);
-            while (!rtems_chain_is_tail (&unresolved->blocks, reindex_node))
-            {
-              rtems_rtl_unresolv_rec*   reindex_rec;
-              rtems_rtl_unresolv_block* reindex_block;
-              reindex_block = (rtems_rtl_unresolv_block*) reindex_node;
-              if (reindex_first != NULL)
-              {
-                reindex_rec = reindex_first;
-                reindex_first = NULL;
-              }
-              else
-              {
-                reindex_rec = rtems_rtl_unresolved_rec_first (reindex_block);
-              }
-              while (!rtems_rtl_unresolved_rec_is_last (reindex_block,
-                                                        reindex_rec))
-              {
-                if (reindex_rec->type == rtems_rtl_unresolved_reloc)
-                {
-                  if (reindex_rec->rec.reloc.name >= index)
-                    --reindex_rec->rec.reloc.name;
-                }
-                reindex_rec = rtems_rtl_unresolved_rec_next (reindex_rec);
-              }
-              reindex_node = rtems_chain_next (reindex_node);
-            }
+            rtems_rtl_unresolved_reindex_names (index, -1);
             /*
              * Compact the block removing the name record.
              */
@@ -470,11 +529,9 @@ rtems_rtl_unresolved_add (rtems_rtl_obj*        obj,
                           const rtems_rtl_word* rel)
 {
   rtems_rtl_unresolved*     unresolved;
-  rtems_chain_node*         node;
   rtems_rtl_unresolv_block* block;
   rtems_rtl_unresolv_rec*   rec;
   int                       name_index;
-  size_t                    name_recs;
 
   if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
     printf ("rtl: unresolv: add: %s(s:%d) -> %s\n",
@@ -485,69 +542,69 @@ rtems_rtl_unresolved_add (rtems_rtl_obj*        obj,
     return false;
 
   /*
-   * Find the first block with a spare record.
-   */
-  node = rtems_chain_first (&unresolved->blocks);
-  block = NULL;
-  while (!rtems_chain_is_tail (&unresolved->blocks, node))
-  {
-    block = (rtems_rtl_unresolv_block*) node;
-    if (block->recs < unresolved->block_recs)
-      break;
-    block = NULL;
-    node = rtems_chain_next (node);
-  }
-
-  /*
-   * No blocks with any spare records, allocate a new block.
+   * Is the name present?
    */
-  if (!block)
-  {
-    block = rtems_rtl_unresolved_block_alloc (unresolved);
-    if (!block)
-      return false;
-  }
-
-  name_index = rtems_rtl_unresolved_find_name (unresolved, name, true);
-  name_recs = rtems_rtl_unresolved_symbol_recs (name);
+  name_index = rtems_rtl_unresolved_find_name (name);
 
   /*
-   * An index less than 0 means the name is present and "0 - index" is the next
-   * index to use.
+   * An index less than 0 means the name was not found.
    */
   if (name_index < 0)
   {
-    rtems_rtl_unresolv_block* name_block = block;
+    size_t name_recs;
+
+    name_recs = rtems_rtl_unresolved_symbol_recs (name);
 
     /*
      * Is there enough room to fit the name ? It not add a new block.
      */
-    if (name_recs > (unresolved->block_recs - block->recs))
+    block = rtems_rtl_unresolved_alloc_recs (unresolved, name_recs);
+    if (block == NULL)
     {
-      name_block = rtems_rtl_unresolved_block_alloc (unresolved);
-      if (!name_block)
+      block = rtems_rtl_unresolved_block_alloc (unresolved);
+      if (!block)
         return false;
     }
 
-    rec = rtems_rtl_unresolved_rec_first_free (name_block);
+    /*
+     * Find the record in the block.
+     */
+    rec = rtems_rtl_unresolved_rec_first_free (block);
+
+    /*
+     * Enter the new record before reindexing so the iterator can see
+     * it and the iterator is called.
+     */
     rec->type = rtems_rtl_unresolved_symbol;
     rec->rec.name.refs = 1;
     rec->rec.name.flags = RTEMS_RTL_UNRESOLV_SYM_SEARCH_ARCHIVE;
     rec->rec.name.length = strlen (name) + 1;
-    memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length + 1);
+    memcpy ((void*) &rec->rec.name.name[0], name, rec->rec.name.length);
     block->recs += name_recs;
-    name_index = 0 - name_index;
 
     /*
-     * If the name block is the reloc block and it is full allocate a new
-     * block for the relocation record.
+     * Find the name index for the name and then reindex the names which
+     * are moved up because of the insertion.
      */
-    if ((block == name_block) && (block->recs >= unresolved->block_recs))
+    name_index = rtems_rtl_unresolved_find_index (rec);
+    if (name_index < 0)
     {
-      block = rtems_rtl_unresolved_block_alloc (unresolved);
-      if (!block)
-        return false;
+      rtems_rtl_set_error (ENOMEM, "internal unresolved block error");
+      return false;
     }
+
+    rtems_rtl_unresolved_reindex_names (name_index, 1);
+  }
+
+  /*
+   * Find the first block with a spare record.
+   */
+  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);
@@ -592,7 +649,7 @@ rtems_rtl_unresolved_resolve (void)
     };
     rtems_rtl_unresolved_archive_reloc_data ard = {
       .name = 0,
-      .loaded = false,
+      .result = rtems_rtl_archive_search_not_found,
       .archives = rtems_rtl_archives_unprotected ()
     };
 
@@ -600,7 +657,7 @@ rtems_rtl_unresolved_resolve (void)
     rtems_rtl_unresolved_compact ();
     rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_iterator, &ard);
 
-    resolving = ard.loaded;
+    resolving = ard.result == rtems_rtl_archive_search_loaded;
   }
 
   if (rtems_rtl_trace (RTEMS_RTL_TRACE_UNRESOLVED))
@@ -627,6 +684,7 @@ typedef struct rtems_rtl_unresolved_dump_data
 {
   size_t rec;
   size_t names;
+  bool   show_relocs;
 } rtems_rtl_unresolved_dump_data;
 
 static bool
@@ -642,16 +700,20 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
     break;
   case rtems_rtl_unresolved_symbol:
     ++dd->names;
-    printf (" %3zu: 1:  name: %3d refs: %2d: %2d: %s\n",
+    printf (" %3zu: 1:  name: %3d refs:%4d: flags:%04x %s (%d)\n",
             dd->rec, dd->names,
-            rec->rec.name.refs, rec->rec.name.length, rec->rec.name.name);
+            rec->rec.name.refs,
+            rec->rec.name.flags,
+            rec->rec.name.name,
+            rec->rec.name.length);
     break;
   case rtems_rtl_unresolved_reloc:
-    printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
-            dd->rec,
-            rec->rec.reloc.obj->oname,
-            rec->rec.reloc.name,
-            rec->rec.reloc.sect);
+    if (dd->show_relocs)
+      printf (" %3zu: 2: reloc: obj:%s name:%2d: sect:%d\n",
+              dd->rec,
+              rec->rec.reloc.obj == NULL ? "resolved" : rec->rec.reloc.obj->oname,
+              rec->rec.reloc.name,
+              rec->rec.reloc.sect);
     break;
   default:
     printf (" %03zu: %d: unknown\n", dd->rec, rec->type);
@@ -662,16 +724,16 @@ rtems_rtl_unresolved_dump_iterator (rtems_rtl_unresolv_rec* rec,
 }
 
 void
-rtems_rtl_unresolved_set_archive_search (void)
-{
-  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
-                                NULL);
-}
-
-void
 rtems_rtl_unresolved_dump (void)
 {
   rtems_rtl_unresolved_dump_data dd = { 0 };
   printf ("RTL Unresolved data:\n");
   rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_dump_iterator, &dd);
 }
+
+void
+rtems_rtl_unresolved_set_archive_search (void)
+{
+  rtems_rtl_unresolved_iterate (rtems_rtl_unresolved_archive_search_iterator,
+                                NULL);
+}
diff --git a/cpukit/libdl/rtl.c b/cpukit/libdl/rtl.c
index a3664c7..e3dba5a 100644
--- a/cpukit/libdl/rtl.c
+++ b/cpukit/libdl/rtl.c
@@ -144,7 +144,7 @@ rtems_rtl_data_init (void)
       /*
        * Open the archives.
        */
-      rtems_rtl_archives_open (&rtl->archives, "/etc/rtl-libs.conf");
+      rtems_rtl_archives_open (&rtl->archives, "/etc/libdl.conf");
 
       /*
        * Open the unresolved table.
@@ -265,6 +265,14 @@ rtems_rtl_global_symbols (void)
   return &rtl->globals;
 }
 
+const char*
+rtems_rtl_last_error_unprotected (void)
+{
+  if (!rtl)
+    return NULL;
+  return rtl->last_error;
+}
+
 rtems_chain_control*
 rtems_rtl_objects_unprotected (void)
 {
diff --git a/testsuites/libtests/Makefile.am b/testsuites/libtests/Makefile.am
index 22cf613..166f45e 100644
--- a/testsuites/libtests/Makefile.am
+++ b/testsuites/libtests/Makefile.am
@@ -576,16 +576,19 @@ dl08-o5.o: dl08/dl-o5.c Makefile
 	$(AM_V_CC)$(COMPILE) -c -o $@ $<
 dl08-o6-123456789-123456789.o: dl08/dl-o6-123456789-123456789.c Makefile
 	$(AM_V_CC)$(COMPILE) -c -o $@ $<
-#	echo "#" > etc/rtl-libs.conf
-#	echo "  # blah blah" >> etc/rtl-libs.conf
-etc/rtl-libs.conf:
+etc/libdl.conf:
 	mkdir etc; \
-	echo "/libdl08*.a" >> etc/rtl-libs.conf
+	echo "#" > etc/libdl.conf
+	echo "  # blah blah" >> etc/libdl.conf
+	echo "/libdl08*.a" >> etc/libdl.conf
+	echo "" >> etc/libdl.conf
+	echo "x" >> etc/libdl.conf
+	echo "" >> etc/libdl.conf
 noinst_LIBRARIES = libdl08_1.a libdl08_2.a
 libdl08_1_a_SOURCES = dl08-o2.c dl08-o4.c
 libdl08_2_a_SOURCES = dl08-o3.c dl08-o5.c \
 			dl08-o6-123456789-123456789.c
-dl08.tar: etc/rtl-libs.conf dl08-o1.o libdl08_1.a libdl08_2.a
+dl08.tar: etc/libdl.conf dl08-o1.o libdl08_1.a libdl08_2.a
 	@rm -f $@
 	$(AM_V_GEN)$(PAX) -w -f $@ $+
 dl08-tar.c: dl08.tar
@@ -601,7 +604,7 @@ dl08$(EXEEXT):  $(dl08_OBJECTS) $(dl08_DEPENDENCIES) dl08-sym.o
 	$(AM_V_CCLD)$(LINK.c) $(CPU_CFLAGS) $(AM_CFLAGS) $(AM_LDFLAGS) -o $@ $+
 CLEANFILES += dl08.pre dl08-sym.o libdl08_1.a libdl08_2.a dl08-o1.o dl08-o2.o \
 		dl08-o3.o dl08-o4.o dl08-o5.o dl08-o6-123456789-123456789.o \
-		dl08.tar dl08-tar.h etc/rtl-libs.conf
+		dl08.tar dl08-tar.h etc/libdl.conf
 endif
 endif
 
diff --git a/testsuites/libtests/dl08/dl-load.c b/testsuites/libtests/dl08/dl-load.c
index 6f4c6f3..44330e8 100644
--- a/testsuites/libtests/dl08/dl-load.c
+++ b/testsuites/libtests/dl08/dl-load.c
@@ -15,11 +15,13 @@
                       RTEMS_RTL_TRACE_UNLOAD | \
                       RTEMS_RTL_TRACE_SYMBOL | \
                       RTEMS_RTL_TRACE_RELOC | \
+                      RTEMS_RTL_TRACE_LOAD_SECT | \
                       RTEMS_RTL_TRACE_ALLOCATOR | \
                       RTEMS_RTL_TRACE_UNRESOLVED | \
                       RTEMS_RTL_TRACE_ARCHIVES | \
                       RTEMS_RTL_TRACE_DEPENDENCY)
- #define DL_DEBUG_TRACE DEBUG_TRACE /* RTEMS_RTL_TRACE_ALL */
+ /* RTEMS_RTL_TRACE_ALL */
+ #define DL_DEBUG_TRACE DEBUG_TRACE
  #define DL_RTL_CMDS    1
 #else
  #define DL_DEBUG_TRACE 0
diff --git a/testsuites/libtests/dl09/dl-load.c b/testsuites/libtests/dl09/dl-load.c
index ee0ef0a..160f815 100644
--- a/testsuites/libtests/dl09/dl-load.c
+++ b/testsuites/libtests/dl09/dl-load.c
@@ -99,7 +99,7 @@ static void dl_check_resolved(void* handle, bool has_unresolved)
           handle, unresolved != 0 ? "" : "no ");
 }
 
-static void* dl_load_obj(const char* name, bool has_unresolved)
+static void* dl_load_obj (const char* name, bool has_unresolved)
 {
   void* handle;
 
@@ -184,11 +184,17 @@ int dl_load_test(void)
 
   dl_load_dump ();
 
+  /*
+   * Check for any resolved externals.
+   */
+  printf ("Check is any unresolved externals exist:\n");
+  dl_check_resolved (RTLD_SELF, false);
+
   printf ("Running rtems_main_o1:\n");
   if (dl_call (o[0].handle, "rtems_main_o1"))
     return 1;
 
-  for (i = 0; i < NUMOF(od); ++i)
+  for (i = 0; i < NUMOF (od); ++i)
     dl_object_close (&o[i]);
 
   return 0;
diff --git a/testsuites/libtests/dl09/dl-o5.c b/testsuites/libtests/dl09/dl-o5.c
index 84e8c84..fc02e19 100644
--- a/testsuites/libtests/dl09/dl-o5.c
+++ b/testsuites/libtests/dl09/dl-o5.c
@@ -7,6 +7,7 @@
  */
 
 #include "dl-load.h"
+#include "dl-o4.h"
 #include "dl-o5.h"
 
 #include <inttypes.h>



More information about the vc mailing list