Index: linkers/rld-files.cpp
===================================================================
--- linkers/rld-files.cpp	(revision ec24a379bcea34b0b080c84908e4cace969893f7)
+++ linkers/rld-files.cpp	(revision 977c3de534bb5cce7935b47138efc2eac8e5ae23)
@@ -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
@@ -46,5 +46,5 @@
     {
       uint64_t value = 0;
-      
+
       while (len && (*string != ' '))
       {
@@ -105,5 +105,5 @@
       else if ((path_[path_.size () - 1] == RLD_PATH_SEPARATOR) &&
                (file_[0] == RLD_PATH_SEPARATOR))
-        joined = path_ + &file_[1];        
+        joined = path_ + &file_[1];
       else
         joined = path_ + file_;
@@ -148,5 +148,5 @@
                 off_t              offset,
                 size_t             size)
-      : aname_ (aname), 
+      : aname_ (aname),
         oname_ (oname),
         offset_ (offset),
@@ -247,6 +247,6 @@
       return oname_;
     }
-    
-    const std::string 
+
+    const std::string
     file::full () const
     {
@@ -298,6 +298,5 @@
       : name_ (name),
         references_ (0),
-        fd_ (-1),
-        elf_ (0)
+        fd_ (-1)
     {
     }
@@ -307,6 +306,6 @@
         references_ (0),
         fd_ (-1),
-        elf_ (0),
-        symbol_refs (0)
+        symbol_refs (0),
+        writeable (false)
     {
     }
@@ -315,5 +314,4 @@
       : references_ (0),
         fd_ (-1),
-        elf_ (0),
         symbol_refs (0)
     {
@@ -336,18 +334,21 @@
 
     void
-    image::open (bool writable)
+    image::open (bool writeable_)
     {
       const std::string path = name_.path ();
 
       if (path.empty ())
-        throw rld::error ("No file name", "open" + path);
+        throw rld::error ("No file name", "open:" + path);
 
       if (rld::verbose () >= RLD_VERBOSE_DETAILS)
         std::cout << "image::open: " << name (). full ()
+                  << " writable:" << (char*) (writeable_ ? "yes" : "no")
                   << " refs:" << references_ + 1 << std::endl;
 
       if (fd_ < 0)
       {
-        if (writable)
+        writeable = writeable_;
+
+        if (writeable)
           fd_ = ::open (path.c_str (), OPEN_FLAGS | O_RDWR | O_CREAT | O_TRUNC, CREATE_MODE);
         else
@@ -356,4 +357,9 @@
           throw rld::error (::strerror (errno), "open:" + path);
       }
+      else
+      {
+        if (writeable_ != writeable)
+          throw rld::error ("Cannot change write status", "open:" + path);
+      }
 
       ++references_;
@@ -386,5 +392,5 @@
       return rsize;
     }
- 
+
     ssize_t
     image::write (const void* buffer, size_t size)
@@ -395,5 +401,5 @@
       return wsize;
     }
- 
+
     void
     image::seek (off_t offset)
@@ -402,5 +408,5 @@
         throw rld::error (strerror (errno), "lseek:" + name ().path ());
     }
- 
+
     bool
     image::seek_read (off_t offset, uint8_t* buffer, size_t size)
@@ -409,5 +415,5 @@
       return size == (size_t) read (buffer, size);
     }
- 
+
     bool
     image::seek_write (off_t offset, const void* buffer, size_t size)
@@ -416,5 +422,5 @@
       return size == (size_t) write (buffer, size);
     }
- 
+
     const file&
     image::name () const
@@ -424,5 +430,5 @@
 
     int
-    image::references () const 
+    image::references () const
     {
       return references_;
@@ -430,5 +436,5 @@
 
     size_t
-    image::size () const 
+    image::size () const
     {
       return name ().size ();
@@ -436,11 +442,11 @@
 
     int
-    image::fd () const 
+    image::fd () const
     {
       return fd_;
     }
 
-    rld::elf::elf*
-    image::elf (bool )
+    rld::elf::file&
+    image::elf ()
     {
       return elf_;
@@ -448,15 +454,9 @@
 
     void
-    image::set_elf (rld::elf::elf* elf)
-    {
-      elf_ = elf;
-    }
-
-    void
     image::symbol_referenced ()
     {
       ++symbol_refs;
     }
-    
+
     int
     image::symbol_references () const
@@ -475,4 +475,8 @@
         while (size)
         {
+          /*
+           * @fixme the reading and writing are not POSIX; sigints could split them.
+           */
+
           size_t l = size < COPY_FILE_BUFFER_SIZE ? size : COPY_FILE_BUFFER_SIZE;
           ssize_t r = ::read (in.fd (), buffer, l);
@@ -546,4 +550,23 @@
     }
 
+    void
+    archive::begin ()
+    {
+      elf ().begin (name ().full (), fd ());
+
+      /*
+       * Make sure it is an archive.
+       */
+      if (!elf ().is_archive ())
+        throw rld::error ("Not an archive.",
+                          "archive-begin:" + name ().full ());
+    }
+
+    void
+    archive::end ()
+    {
+      elf ().end ();
+    }
+
     bool
     archive::is (const std::string& path) const
@@ -581,6 +604,6 @@
          * The archive file headers are always aligned to an even address.
          */
-        size = 
-          (scan_decimal (&header[rld_archive_size], 
+        size =
+          (scan_decimal (&header[rld_archive_size],
                          rld_archive_size_size) + 1) & ~1;
 
@@ -626,13 +649,13 @@
                 while (extended_file_names == 0)
                 {
-                  size_t esize = 
+                  size_t esize =
                     (scan_decimal (&header[rld_archive_size],
                                    rld_archive_size_size) + 1) & ~1;
                   off += esize + rld_archive_fhdr_size;
-                    
+
                   if (!read_header (off, &header[0]))
                     throw rld::error ("No GNU extended file name section found",
                                       "get-names:" + name ().path ());
-              
+
                   if ((header[0] == '/') && (header[1] == '/'))
                   {
@@ -694,5 +717,5 @@
         throw rld::error ("Invalid header magic numbers at " +
                           rld::to_string (offset), "read-header:" + name ().path ());
-      
+
       return true;
     }
@@ -726,5 +749,5 @@
 
         memset (header, ' ', sizeof (header));
-        
+
         size_t len = name.length ();
         if (len > rld_archive_fname_size)
@@ -757,5 +780,5 @@
          */
         std::string extended_file_names;
-        
+
         for (object_list::iterator oi = objects.begin ();
              oi != objects.end ();
@@ -819,5 +842,5 @@
         throw;
       }
-      
+
       close ();
     }
@@ -878,8 +901,26 @@
     {
       /*
-       * Begin an ELF session and get the ELF header.
+       * Begin a session.
        */
-      rld::elf::begin (*this);
-      rld::elf::get_header (*this, ehdr);
+      if (archive_)
+        elf ().begin (name ().full (), archive_->elf(), name ().offset ());
+      else
+        elf ().begin (name ().full (), fd ());
+
+      /*
+       * Cannot be an archive.
+       */
+      if (elf ().is_archive ())
+        throw rld::error ("Is an archive not an object file.",
+                          "object-begin:" + name ().full ());
+
+      /*
+       * We only support executable or relocatable ELF files.
+       */
+      if (!elf ().is_executable () && !elf ().is_relocatable ())
+        throw rld::error ("Invalid ELF type (only ET_EXEC/ET_REL supported).",
+                          "object-begin:" + name ().full ());
+
+      elf::check_file (elf ());
     }
 
@@ -887,5 +928,5 @@
     object::end ()
     {
-      rld::elf::end (*this);
+      elf ().end ();
     }
 
@@ -895,15 +936,56 @@
       if (rld::verbose () >= RLD_VERBOSE_DETAILS)
         std::cout << "object:load-sym: " << name ().full () << std::endl;
-      rld::elf::load_symbols (symbols, *this, local);
-    }
-
-    std::string
-    object::get_string (int section, size_t offset)
-    {
-      return rld::elf::get_string (*this, section, offset);
-    }
-    
+
+      rld::symbols::pointers syms;
+
+      elf ().get_symbols (syms, false, local);
+
+      if (rld::verbose () >= RLD_VERBOSE_DETAILS)
+        std::cout << "object:load-sym: exported: 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_DETAILS)
+        {
+          std::cout << "object:load-sym: exported: ";
+          sym.output (std::cout);
+          std::cout << std::endl;
+        }
+
+        sym.set_object (*this);
+        symbols[sym.name ()] = &sym;
+        externals.push_back (&sym);
+      }
+
+      elf ().get_symbols (syms, true);
+
+      if (rld::verbose () >= RLD_VERBOSE_DETAILS)
+        std::cout << "object:load-sym: unresolved: 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_DETAILS)
+        {
+          std::cout << "object:load-sym: unresolved: ";
+          sym.output (std::cout);
+          std::cout << std::endl;
+        }
+
+        unresolved[sym.name ()] = &sym;
+      }
+    }
+
     int
-    object::references () const 
+    object::references () const
     {
       if (archive_)
@@ -913,5 +995,5 @@
 
     size_t
-    object::size () const 
+    object::size () const
     {
       if (archive_)
@@ -921,5 +1003,5 @@
 
     int
-    object::fd () const 
+    object::fd () const
     {
       if (archive_)
@@ -928,12 +1010,4 @@
     }
 
-    rld::elf::elf* 
-    object::elf (bool archive__)
-    {
-      if (archive__ && archive_)
-        return archive_->elf ();
-      return image::elf ();
-    }
-
     void
     object::symbol_referenced ()
@@ -943,5 +1017,5 @@
         archive_->symbol_referenced ();
     }
-    
+
     archive*
     object::get_archive ()
@@ -950,4 +1024,5 @@
     }
 
+#if 0
     int
     object::sections () const
@@ -961,4 +1036,5 @@
       return ehdr.e_shstrndx;
     }
+#endif
 
     rld::symbols::table&
@@ -968,5 +1044,5 @@
     }
 
-    rld::symbols::list&
+    rld::symbols::pointers&
     object::external_symbols ()
     {
@@ -1048,5 +1124,5 @@
             std::cout << "cache:archive-begin: " << path << std::endl;
           ar->open ();
-          rld::elf::begin (*ar);
+          ar->begin ();
         }
       }
@@ -1064,5 +1140,5 @@
           if (rld::verbose () >= RLD_VERBOSE_TRACE)
             std::cout << "cache:archive-end: " << path << std::endl;
-          rld::elf::end (*ar);
+          ar->end ();
           ar->close ();
         }
@@ -1083,5 +1159,5 @@
         archive_end (((*ai).second)->path ());
     }
-    
+
     void
     cache::collect_object_files ()
@@ -1174,5 +1250,5 @@
       return archives_;
     }
- 
+
     objects&
     cache::get_objects ()
