Index: linkers/rld-elf.cpp
===================================================================
--- linkers/rld-elf.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-elf.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -854,12 +854,12 @@
             add = true;
         }
-        else if (!unresolved)
+        else
         {
           if (((stype == STT_NOTYPE) ||
                (stype == STT_OBJECT) ||
                (stype == STT_FUNC)) &&
-              ((local && (sbind == STB_LOCAL)) ||
-                  (weak && (sbind == STB_WEAK)) ||
-               (global && (sbind == STB_GLOBAL))))
+              ((weak && (sbind == STB_WEAK)) ||
+               (!unresolved && ((local && (sbind == STB_LOCAL)) ||
+                                (global && (sbind == STB_GLOBAL))))))
             add = true;
         }
Index: linkers/rld-files.cpp
===================================================================
--- linkers/rld-files.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-files.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -980,5 +980,7 @@
       : image (name_),
         archive_ (&archive_),
-        valid_ (false)
+        valid_ (false),
+        resolving_ (false),
+        resolved_ (false)
     {
       if (!name ().is_valid ())
@@ -989,5 +991,7 @@
       : image (path),
         archive_ (0),
-        valid_ (false)
+        valid_ (false),
+        resolving_ (false),
+        resolved_ (false)
     {
       if (!name ().is_valid ())
@@ -997,5 +1001,7 @@
     object::object ()
       : archive_ (0),
-        valid_ (false)
+        valid_ (false),
+        resolving_ (false),
+        resolved_ (false)
     {
     }
@@ -1117,5 +1123,5 @@
       rld::symbols::pointers syms;
 
-      elf ().get_symbols (syms, false, local);
+      elf ().get_symbols (syms, false, local, false, true);
 
       if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
@@ -1133,9 +1139,29 @@
 
         sym.set_object (*this);
-        symbols[sym.name ()] = &sym;
+        symbols.add_external (sym);
         externals.push_back (&sym);
       }
 
-      elf ().get_symbols (syms, true);
+      elf ().get_symbols (syms, false, false, true, false);
+
+      if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
+        std::cout << "object:load-sym: weak: total "
+                  << syms.size () << std::endl;
+
+      for (symbols::pointers::iterator si = syms.begin ();
+           si != syms.end ();
+           ++si)
+      {
+        symbols::symbol& sym = *(*si);
+
+        if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
+          std::cout << "object:load-sym: weak: " << sym << std::endl;
+
+        sym.set_object (*this);
+        symbols.add_weak (sym);
+        externals.push_back (&sym);
+      }
+
+      elf ().get_symbols (syms, true, false, true, true);
 
       if (rld::verbose () >= RLD_VERBOSE_TRACE_SYMS)
@@ -1216,5 +1242,5 @@
     }
 
-    rld::symbols::table&
+    rld::symbols::symtab&
     object::unresolved_symbols ()
     {
@@ -1280,4 +1306,34 @@
       throw rld::error ("Section index '" + rld::to_string (index) +
                         "' not found: " + name ().full (), "object::get-section");
+    }
+
+    void
+    object::resolve_set ()
+    {
+      resolving_ = true;
+    }
+
+    void
+    object::resolve_clear ()
+    {
+      resolving_ = false;
+    }
+
+    bool
+    object::resolving () const
+    {
+      return resolving_;
+    }
+
+    void
+    object::resolved_set ()
+    {
+      resolved_ = true;
+    }
+
+    bool
+    object::resolved () const
+    {
+      return resolved_;
     }
 
Index: linkers/rld-files.h
===================================================================
--- linkers/rld-files.h	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-files.h	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -57,10 +57,10 @@
      * Container of archive files.
      */
-    typedef std::map < std::string, archive* > archives;
+    typedef std::map < const std::string, archive* > archives;
 
     /**
      * Container of object files.
      */
-    typedef std::map < std::string, object* > objects;
+    typedef std::map < const std::string, object* > objects;
 
     /**
@@ -701,5 +701,5 @@
        * Return the unresolved symbol table for this object file.
        */
-      symbols::table& unresolved_symbols ();
+      symbols::symtab& unresolved_symbols ();
 
       /**
@@ -742,11 +742,38 @@
       const section& get_section (int index) const;
 
+      /**
+       * Set the object file's resolving flag.
+       */
+      void resolve_set ();
+
+      /**
+       * Clear the object file's resolving flag.
+       */
+      void resolve_clear ();
+
+      /**
+       * The resolving state.
+       */
+      bool resolving () const;
+
+      /**
+       * Set the object file resolved flag.
+       */
+      void resolved_set ();
+
+      /**
+       * The resolved state.
+       */
+      bool resolved () const;
+
     private:
       archive*          archive_;   //< Points to the archive if part of an
                                     //  archive.
       bool              valid_;     //< If true begin has run and finished.
-      symbols::table    unresolved; //< This object's unresolved symbols.
+      symbols::symtab   unresolved; //< This object's unresolved symbols.
       symbols::pointers externals;  //< This object's external symbols.
       sections          secs;       //< The sections.
+      bool              resolving_; //< The object is being resolved.
+      bool              resolved_;  //< The object has been resolved.
 
       /**
Index: linkers/rld-outputter.cpp
===================================================================
--- linkers/rld-outputter.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-outputter.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -89,8 +89,8 @@
         out << "o:" << name << std::endl;
 
-        symbols::table& unresolved = obj.unresolved_symbols ();
+        symbols::symtab& unresolved = obj.unresolved_symbols ();
 
         int count = 0;
-        for (symbols::table::iterator ursi = unresolved.begin ();
+        for (symbols::symtab::iterator ursi = unresolved.begin ();
              ursi != unresolved.begin ();
              ++ursi)
Index: linkers/rld-resolver.cpp
===================================================================
--- linkers/rld-resolver.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-resolver.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -39,12 +39,25 @@
   namespace resolver
   {
+    static files::object*
+    get_object (files::cache&      cache,
+                const std::string& fullname)
+    {
+      files::objects&          objects = cache.get_objects ();
+      files::objects::iterator oi = objects.find (fullname);
+      if (oi == objects.end ())
+        return 0;
+      return (*oi).second;
+    }
+
     static void
-    resolve_symbols (rld::files::object_list& dependents,
-                     rld::files::cache&       cache,
-                     rld::symbols::table&     base_symbols,
-                     rld::symbols::table&     symbols,
-                     rld::symbols::table&     unresolved,
-                     const std::string&       name)
+    resolve_symbols (files::object_list& dependents,
+                     files::cache&       cache,
+                     symbols::table&     base_symbols,
+                     symbols::table&     symbols,
+                     symbols::symtab&    unresolved,
+                     const std::string&  fullname)
     {
+      const std::string name = files::basename (fullname);
+
       static int nesting = 0;
 
@@ -59,4 +72,21 @@
        * 'es' is the exported symbol.
        */
+
+      files::object* object = get_object (cache, fullname);
+
+      if (object)
+      {
+        if (object->resolved () || object->resolving ())
+        {
+          if (rld::verbose () >= RLD_VERBOSE_INFO)
+            std::cout << "resolver:resolving: "
+                      << std::setw (nesting - 1) << ' '
+                      << name
+                      << " is resolved or resolving"
+                      << std::endl;
+          return;
+        }
+        object->resolve_set ();
+      }
 
       if (rld::verbose () >= RLD_VERBOSE_INFO)
@@ -68,13 +98,17 @@
                   << std::endl;
 
-      rld::files::object_list objects;
-
-      for (rld::symbols::table::iterator ursi = unresolved.begin ();
-           (ursi != unresolved.end ()) && !((*ursi).second)->object ();
+      files::object_list objects;
+
+      for (symbols::symtab::iterator ursi = unresolved.begin ();
+           ursi != unresolved.end ();
            ++ursi)
       {
-        rld::symbols::symbol&         urs = *((*ursi).second);
-        rld::symbols::table::iterator esi = base_symbols.find (urs.name ());
-        bool                          base = true;
+        symbols::symbol& urs = *((*ursi).second);
+
+        if ((urs.binding () != STB_WEAK) && urs.object ())
+          continue;
+
+        symbols::symbol* es = base_symbols.find_external (urs.name ());
+        bool             base = true;
 
         if (rld::verbose () >= RLD_VERBOSE_INFO)
@@ -82,16 +116,20 @@
           std::cout << "resolver:resolve  : "
                     << std::setw (nesting + 1) << ' '
-                    << urs.name () << std::endl;
-        }
-
-        if (esi == base_symbols.end ())
-        {
-          esi = symbols.find (urs.name ());
-          if (esi == symbols.end ())
-            throw rld::error ("symbol not found: " + urs.name (), name);
+                    << " |- " << urs.name () << std::endl;
+        }
+
+        if (!es)
+        {
+          es = symbols.find_external (urs.name ());
+          if (!es)
+          {
+            es = symbols.find_weak (urs.name ());
+            if (!es)
+              throw rld::error ("symbol not found: " + urs.name (), name);
+          }
           base = false;
         }
 
-        rld::symbols::symbol& es = *((*esi).second);
+        symbols::symbol& esym = *es;
 
         if (rld::verbose () >= RLD_VERBOSE_INFO)
@@ -99,8 +137,17 @@
           std::cout << "resolver:resolved : "
                     << std::setw (nesting + 1) << ' '
-                    << urs.name ()
-                    << " -> ";
-          if (es.object())
-            std::cout << es.object()->name ().basename ();
+                    << " |   `--> ";
+          if (esym.object())
+          {
+            std::cout << esym.object()->name ().basename ();
+            if (esym.object()->resolving ())
+              std::cout << " (resolving)";
+            else if (esym.object()->resolved ())
+              std::cout << " (resolved)";
+            else if (base)
+              std::cout << " (base)";
+            else
+              std::cout << " (unresolved: " << objects.size () + 1 << ')';
+          }
           else
             std::cout << "null";
@@ -110,28 +157,45 @@
         if (!base)
         {
-          urs.set_object (*es.object ());
-          objects.push_back (es.object ());
-        }
-
-        es.referenced ();
-      }
-
-      /*
-       * Recurse into any references object files. First remove any duplicate
-       * entries.
-       */
-      objects.unique ();
-
-      for (rld::files::object_list::iterator oli = objects.begin ();
+          files::object& eobj = *esym.object ();
+          urs.set_object (eobj);
+          if (!eobj.resolved () && !eobj.resolving ())
+          {
+            objects.push_back (&eobj);
+            objects.unique ();
+          }
+        }
+
+        esym.referenced ();
+      }
+
+      if (object)
+      {
+        object->resolve_clear ();
+        object->resolved_set ();
+      }
+
+      /*
+       * Recurse into any references object files.
+       */
+
+      if (rld::verbose () >= RLD_VERBOSE_INFO)
+        std::cout << "resolver:resolved : "
+                  << std::setw (nesting + 1) << ' '
+                  << " +-- referenced objects: " << objects.size ()
+                  << std::endl;
+
+      for (files::object_list::iterator oli = objects.begin ();
            oli != objects.end ();
            ++oli)
       {
-        rld::files::object& object = *(*oli);
-        if (rld::verbose () >= RLD_VERBOSE_INFO)
-          std::cout << "resolver:resolving:    : "
-                    << object.name ().basename () << std::endl;
+        files::object& obj = *(*oli);
+        if (rld::verbose () >= RLD_VERBOSE_INFO)
+          std::cout << "resolver:resolving: "
+                    << std::setw (nesting) << ' '
+                    << "] " << name << " ==> "
+                    << obj.name ().basename () << std::endl;
         resolve_symbols (dependents, cache, base_symbols, symbols,
-                         object.unresolved_symbols (),
-                         object.name ().basename ());
+                         obj.unresolved_symbols (),
+                         obj.name ().full ());
       }
 
@@ -143,11 +207,11 @@
 
     void
-    resolve (rld::files::object_list& dependents,
-             rld::files::cache&       cache,
-             rld::symbols::table&     base_symbols,
-             rld::symbols::table&     symbols,
-             rld::symbols::table&     undefined)
+    resolve (files::object_list& dependents,
+             files::cache&       cache,
+             symbols::table&     base_symbols,
+             symbols::table&     symbols,
+             symbols::symtab&    undefined)
     {
-      rld::files::object_list objects;
+      files::object_list objects;
       cache.get_objects (objects);
 
@@ -162,9 +226,9 @@
        * Resolve the symbols in the object files.
        */
-      for (rld::files::object_list::iterator oi = objects.begin ();
+      for (files::object_list::iterator oi = objects.begin ();
            oi != objects.end ();
            ++oi)
       {
-        rld::files::object& object = *(*oi);
+        files::object& object = *(*oi);
         if (rld::verbose () >= RLD_VERBOSE_INFO)
           std::cout << "resolver:resolving: top: "
@@ -172,5 +236,5 @@
         resolver::resolve_symbols (dependents, cache, base_symbols, symbols,
                                    object.unresolved_symbols (),
-                                   object.name ().basename ());
+                                   object.name ().full ());
       }
     }
Index: linkers/rld-resolver.h
===================================================================
--- linkers/rld-resolver.h	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-resolver.h	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -1,9 +1,9 @@
 /*
- * Copyright (c) 2011, Chris Johns <chrisj@rtems.org> 
+ * Copyright (c) 2011, Chris Johns <chrisj@rtems.org>
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
  * copyright notice and this permission notice appear in all copies.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
@@ -44,9 +44,9 @@
      *                  added for.
      */
-    void resolve (rld::files::object_list& dependents, 
-                  rld::files::cache&       cache,
-                  rld::symbols::table&     base_symbols,
-                  rld::symbols::table&     symbols,
-                  rld::symbols::table&     undefined);
+    void resolve (files::object_list& dependents,
+                  files::cache&       cache,
+                  symbols::table&     base_symbols,
+                  symbols::table&     symbols,
+                  symbols::symtab&    undefined);
   }
 }
Index: linkers/rld-symbols.cpp
===================================================================
--- linkers/rld-symbols.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-symbols.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -267,6 +267,73 @@
     }
 
+    table::table ()
+    {
+    }
+
+    table::~table ()
+    {
+    }
+
+    void
+    table::add_external (symbol& sym)
+    {
+      _externals[sym.name ()] = &sym;
+    }
+
+    void
+    table::add_weak (symbol& sym)
+    {
+      _weaks[sym.name ()] = &sym;
+    }
+
+    symbol*
+    table::find_external (const std::string& name)
+    {
+      symtab::iterator sti = _externals.find (name);
+      if (sti == _externals.end ())
+        return 0;
+      return (*sti).second;
+    }
+
+    symbol*
+    table::find_weak (const std::string& name)
+    {
+      symtab::iterator sti = _weaks.find (name);
+      if (sti == _weaks.end ())
+        return 0;
+      return (*sti).second;
+    }
+
+    size_t
+    table::size () const
+    {
+      return _externals.size () + _weaks.size ();
+    }
+
+    const symtab&
+    table::externals () const
+    {
+      return _externals;
+    }
+
+    const symtab&
+    table::weaks () const
+    {
+      return _weaks;
+    }
+
     void
     load (bucket& bucket_, table& table_)
+    {
+      for (bucket::iterator sbi = bucket_.begin ();
+           sbi != bucket_.end ();
+           ++sbi)
+      {
+        table_.add_external (*sbi);
+      }
+    }
+
+    void
+    load (bucket& bucket_, symtab& table_)
     {
       for (bucket::iterator sbi = bucket_.begin ();
@@ -298,7 +365,16 @@
     output (std::ostream& out, const table& symbols)
     {
+      out << "Externals:" << std::endl;
+      output (out, symbols.externals ());
+      out << "Weaks:" << std::endl;
+      output (out, symbols.weaks ());
+    }
+
+    void
+    output (std::ostream& out, const symtab& symbols)
+    {
       std::cout << " No.  Scope      Type        Address    Size    Name" << std::endl;
       int index = 0;
-      for (table::const_iterator si = symbols.begin ();
+      for (symtab::const_iterator si = symbols.begin ();
            si != symbols.end ();
            ++si)
Index: linkers/rld-symbols.h
===================================================================
--- linkers/rld-symbols.h	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rld-symbols.h	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -188,5 +188,74 @@
      * symbols held in a bucket.
      */
-    typedef std::map < std::string, symbol* > table;
+    typedef std::map < std::string, symbol* > symtab;
+
+    /**
+     * A symbols contains a symbol table of externals and weak symbols.
+     */
+    class table
+    {
+    public:
+      /**
+       * Construct a table.
+       */
+      table ();
+
+      /**
+       * Destruct a table.
+       */
+      ~table ();
+
+      /**
+       * Add an external symbol.
+       */
+      void add_external (symbol& sym);
+
+      /**
+       * Add a weak symbol.
+       */
+      void add_weak (symbol& sym);
+
+      /**
+       * Find an external symbol.
+       */
+      symbol* find_external (const std::string& name);
+
+      /**
+       * Find an weak symbol.
+       */
+      symbol* find_weak (const std::string& name);
+
+      /**
+       * Return the size of the symbols loaded.
+       */
+      size_t size () const;
+
+      /**
+       * Return the externals symbol table.
+       */
+      const symtab& externals () const;
+
+      /**
+       * Return the weaks symbol table.
+       */
+      const symtab& weaks () const;
+
+    private:
+
+      /**
+       * Cannot copy a table.
+       */
+      table (const table& orig);
+
+      /**
+       * A table of external symbols.
+       */
+      symtab _externals;
+
+      /**
+       * A table of weak symbols.
+       */
+      symtab _weaks;
+    };
 
     /**
@@ -196,4 +265,9 @@
 
     /**
+     * Load a table from a buckey.
+     */
+    void load (bucket& bucket_, symtab& table_);
+
+    /**
      * Given a container of symbols return how many are referenced.
      */
@@ -204,4 +278,9 @@
      */
     void output (std::ostream& out, const table& symbols);
+
+    /**
+     * Output the symbol table.
+     */
+    void output (std::ostream& out, const symtab& symbols);
   }
 }
Index: linkers/rtems-ld.cpp
===================================================================
--- linkers/rtems-ld.cpp	(revision 800d4fd7484cd23bb7e0d19ac5225a54ba9cd492)
+++ linkers/rtems-ld.cpp	(revision 544de91e99b9fbca79916424addb1b987257a6d3)
@@ -171,5 +171,5 @@
     rld::symbols::table  base_symbols;
     rld::symbols::table  symbols;
-    rld::symbols::table  undefined;
+    rld::symbols::symtab undefined;
     std::string          entry = "rtems";
     std::string          exit;
