From Craig Silverstein: Minimal --script implementation.
[deliverable/binutils-gdb.git] / gold / merge.cc
index d2972fdfdb1c89a61c00d92148fca2911442c05d..13bfc177848b9cfede7f98aae6b08aaf596d2fad 100644 (file)
@@ -23,6 +23,7 @@
 #include "gold.h"
 
 #include <cstdlib>
+#include <algorithm>
 
 #include "merge.h"
 
@@ -40,7 +41,15 @@ Output_merge_base::Merge_key_less::operator()(const Merge_key& mk1,
   // matter.  We want to get consistent results across links so we
   // don't use pointer comparison.
   if (mk1.object != mk2.object)
-    return mk1.object->name() < mk2.object->name();
+    {
+      // Two different object files can have the same name: if foo.a
+      // includes both bar/qux.o and baz/qux.o, then both end up with
+      // the name foo.a(qux.o).  But it's impossible for two different
+      // object files to have both the same name and the same offset.
+      if (mk1.object->offset() != mk2.object->offset())
+        return mk1.object->offset() < mk2.object->offset();
+      return mk1.object->name() < mk2.object->name();
+    }
   if (mk1.shndx != mk2.shndx)
     return mk1.shndx < mk2.shndx;
   return mk1.offset < mk2.offset;
@@ -86,7 +95,8 @@ Output_merge_base::do_output_address(const Relobj* object, unsigned int shndx,
 
   // If MK is not in the map, lower_bound returns the next iterator
   // larger than it.
-  if (p->first.object != object
+  if (p == this->merge_map_.end()
+      || p->first.object != object
       || p->first.shndx != shndx
       || p->first.offset != offset)
     {
@@ -152,19 +162,22 @@ void
 Output_merge_data::add_constant(const unsigned char* p)
 {
   uint64_t entsize = this->entsize();
-  if (this->len_ + entsize > this->alc_)
+  uint64_t addsize = std::max(entsize, this->addralign());
+  if (this->len_ + addsize > this->alc_)
     {
       if (this->alc_ == 0)
-       this->alc_ = 128 * entsize;
+       this->alc_ = 128 * addsize;
       else
        this->alc_ *= 2;
       this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->alc_));
       if (this->p_ == NULL)
-       gold_fatal("out of memory", true);
+       gold_nomem();
     }
 
   memcpy(this->p_ + this->len_, p, entsize);
-  this->len_ += entsize;
+  if (addsize > entsize)
+    memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
+  this->len_ += addsize;
 }
 
 // Add the input section SHNDX in OBJECT to a merged output section
@@ -176,7 +189,7 @@ bool
 Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
 {
   off_t len;
-  const unsigned char* p = object->section_contents(shndx, &len);
+  const unsigned char* p = object->section_contents(shndx, &len, false);
 
   uint64_t entsize = this->entsize();
 
@@ -236,43 +249,40 @@ Output_merge_string<Char_type>::do_add_input_section(Relobj* object,
                                                     unsigned int shndx)
 {
   off_t len;
-  const unsigned char* pdata = object->section_contents(shndx, &len);
+  const unsigned char* pdata = object->section_contents(shndx, &len, false);
 
   const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
 
   if (len % sizeof(Char_type) != 0)
     {
-      fprintf(stderr,
-             _("%s: %s: mergeable string section length not multiple of "
-               "character size\n"),
-             program_name, object->name().c_str());
-      gold_exit(false);
+      object->error(_("mergeable string section length not multiple of "
+                     "character size"));
+      return false;
     }
-  len /= sizeof(Char_type);
 
+  // The index I is in bytes, not characters.
   off_t i = 0;
   while (i < len)
     {
       off_t plen = 0;
       for (const Char_type* pl = p; *pl != 0; ++pl)
        {
+          // The length PLEN is in characters, not bytes.
          ++plen;
-         if (i + plen >= len)
+         if (i + plen * static_cast<off_t>(sizeof(Char_type)) >= len)
            {
-             fprintf(stderr,
-                     _("%s: %s: entry in mergeable string section "
-                       "not null terminated\n"),
-                     program_name, object->name().c_str());
-             gold_exit(false);
+             object->error(_("entry in mergeable string section "
+                             "not null terminated"));
+             break;
            }
        }
 
-      const Char_type* str = this->stringpool_.add(p, NULL);
+      const Char_type* str = this->stringpool_.add(p, true, NULL);
 
       this->merged_strings_.push_back(Merged_string(object, shndx, i, str));
 
       p += plen + 1;
-      i += plen + 1;
+      i += (plen + 1) * sizeof(Char_type);
     }
 
   return true;
This page took 0.031437 seconds and 4 git commands to generate.