* powerpc.cc (Powerpc_relocate_functions): Upcase enum values,
[deliverable/binutils-gdb.git] / gold / output.cc
index 12268c9a1f4d91201505fc8c6cfc55a180c16244..664e408bb1e98b8c2ae36897501e1ed2ee02f714 100644 (file)
@@ -111,18 +111,6 @@ extern "C" void *gold_mremap(void *, size_t, size_t, int);
 # define MREMAP_MAYMOVE 1
 #endif
 
-#ifndef HAVE_POSIX_FALLOCATE
-// A dummy, non general, version of posix_fallocate.  Here we just set
-// the file size and hope that there is enough disk space.  FIXME: We
-// could allocate disk space by walking block by block and writing a
-// zero byte into each block.
-static int
-posix_fallocate(int o, off_t offset, off_t len)
-{
-  return ftruncate(o, offset + len);
-}
-#endif // !defined(HAVE_POSIX_FALLOCATE)
-
 // Mingw does not have S_ISLNK.
 #ifndef S_ISLNK
 # define S_ISLNK(mode) 0
@@ -131,6 +119,27 @@ posix_fallocate(int o, off_t offset, off_t len)
 namespace gold
 {
 
+// A wrapper around posix_fallocate.  If we don't have posix_fallocate,
+// or the --no-posix-fallocate option is set, we try the fallocate
+// system call directly.  If that fails, we use ftruncate to set
+// the file size and hope that there is enough disk space.
+
+static int
+gold_fallocate(int o, off_t offset, off_t len)
+{
+#ifdef HAVE_POSIX_FALLOCATE
+  if (parameters->options().posix_fallocate())
+    return ::posix_fallocate(o, offset, len);
+#endif // defined(HAVE_POSIX_FALLOCATE)
+#ifdef HAVE_FALLOCATE
+  if (::fallocate(o, 0, offset, len) == 0)
+    return 0;
+#endif // defined(HAVE_FALLOCATE)
+  if (::ftruncate(o, offset + len) < 0)
+    return errno;
+  return 0;
+}
+
 // Output_data variables.
 
 bool Output_data::allocated_sizes_are_fixed;
@@ -703,10 +712,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_data* od,
     Address address,
     bool is_relative,
-    bool is_symbolless)
+    bool is_symbolless,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -724,10 +734,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int shndx,
     Address address,
     bool is_relative,
-    bool is_symbolless)
+    bool is_symbolless,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(GSYM_CODE), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(use_plt_offset), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -749,10 +760,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address,
     bool is_relative,
     bool is_symbolless,
-    bool is_section_symbol)
+    bool is_section_symbol,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(is_section_symbol), shndx_(INVALID_CODE)
+    is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+    shndx_(INVALID_CODE)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -773,10 +786,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address,
     bool is_relative,
     bool is_symbolless,
-    bool is_section_symbol)
+    bool is_section_symbol,
+    bool use_plt_offset)
   : address_(address), local_sym_index_(local_sym_index), type_(type),
     is_relative_(is_relative), is_symbolless_(is_symbolless),
-    is_section_symbol_(is_section_symbol), shndx_(shndx)
+    is_section_symbol_(is_section_symbol), use_plt_offset_(use_plt_offset),
+    shndx_(shndx)
 {
   gold_assert(local_sym_index != GSYM_CODE
               && local_sym_index != INVALID_CODE);
@@ -796,10 +811,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Output_section* os,
     unsigned int type,
     Output_data* od,
-    Address address)
+    Address address,
+    bool is_relative)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(true), shndx_(INVALID_CODE)
+    is_relative_(is_relative), is_symbolless_(is_relative),
+    is_section_symbol_(true), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -817,10 +833,11 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     unsigned int type,
     Sized_relobj<size, big_endian>* relobj,
     unsigned int shndx,
-    Address address)
+    Address address,
+    bool is_relative)
   : address_(address), local_sym_index_(SECTION_CODE), type_(type),
-    is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(true), shndx_(shndx)
+    is_relative_(is_relative), is_symbolless_(is_relative),
+    is_section_symbol_(true), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -842,7 +859,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -858,7 +875,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(0), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -877,7 +894,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(INVALID_CODE)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(INVALID_CODE)
 {
   // this->type_ is a bitfield; make sure TYPE fits.
   gold_assert(this->type_ == type);
@@ -894,7 +911,7 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::Output_reloc(
     Address address)
   : address_(address), local_sym_index_(TARGET_CODE), type_(type),
     is_relative_(false), is_symbolless_(false),
-    is_section_symbol_(false), shndx_(shndx)
+    is_section_symbol_(false), use_plt_offset_(false), shndx_(shndx)
 {
   gold_assert(shndx != INVALID_CODE);
   // this->type_ is a bitfield; make sure TYPE fits.
@@ -1110,10 +1127,21 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
     {
       const Sized_symbol<size>* sym;
       sym = static_cast<const Sized_symbol<size>*>(this->u1_.gsym);
-      return sym->value() + addend;
+      if (this->use_plt_offset_ && sym->has_plt_offset())
+       {
+         uint64_t plt_address =
+           parameters->target().plt_address_for_global(sym);
+         return plt_address + sym->plt_offset();
+       }
+      else
+       return sym->value() + addend;
     }
-  gold_assert(this->local_sym_index_ != SECTION_CODE
-             && this->local_sym_index_ != TARGET_CODE
+  if (this->local_sym_index_ == SECTION_CODE)
+    {
+      gold_assert(!this->use_plt_offset_);
+      return this->u1_.os->address() + addend;
+    }
+  gold_assert(this->local_sym_index_ != TARGET_CODE
               && this->local_sym_index_ != INVALID_CODE
              && this->local_sym_index_ != 0
               && !this->is_section_symbol_);
@@ -1121,6 +1149,12 @@ Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>::symbol_value(
   Sized_relobj_file<size, big_endian>* relobj =
       this->u1_.relobj->sized_relobj();
   gold_assert(relobj != NULL);
+  if (this->use_plt_offset_)
+    {
+      uint64_t plt_address =
+         parameters->target().plt_address_for_local(relobj, lsi);
+      return plt_address + relobj->local_plt_offset(lsi);
+    }
   const Symbol_value<size>* symval = relobj->local_symbol(lsi);
   return symval->value(relobj, addend);
 }
@@ -1375,11 +1409,13 @@ Output_data_got<size, big_endian>::Got_entry::write(unsigned char* pov) const
 
     default:
       {
-       const Sized_relobj_file<size, big_endian>* object = this->u_.object;
+       const Relobj* object = this->u_.object;
         const unsigned int lsi = this->local_sym_index_;
-        const Symbol_value<size>* symval = object->local_symbol(lsi);
        if (!this->use_plt_offset_)
-         val = symval->value(this->u_.object, 0);
+         {
+           uint64_t lval = object->local_symbol_value(lsi, 0);
+           val = convert_types<Valtype, uint64_t>(lval);
+         }
        else
          {
            uint64_t plt_address =
@@ -1436,7 +1472,7 @@ void
 Output_data_got<size, big_endian>::add_global_with_rel(
     Symbol* gsym,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type)
 {
   if (gsym->has_got_offset(got_type))
@@ -1444,23 +1480,7 @@ Output_data_got<size, big_endian>::add_global_with_rel(
 
   unsigned int got_offset = this->add_got_entry(Got_entry());
   gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global(gsym, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_with_rela(
-    Symbol* gsym,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
-    unsigned int r_type)
-{
-  if (gsym->has_got_offset(got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry(Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rela_dyn->add_global(gsym, r_type, this, got_offset, 0);
+  rel_dyn->add_global_generic(gsym, r_type, this, got_offset, 0);
 }
 
 // Add a pair of entries for a global symbol to the GOT, and add
@@ -1471,27 +1491,7 @@ void
 Output_data_got<size, big_endian>::add_global_pair_with_rel(
     Symbol* gsym,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
-    unsigned int r_type_1,
-    unsigned int r_type_2)
-{
-  if (gsym->has_got_offset(got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
-  gsym->set_got_offset(got_type, got_offset);
-  rel_dyn->add_global(gsym, r_type_1, this, got_offset);
-
-  if (r_type_2 != 0)
-    rel_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_global_pair_with_rela(
-    Symbol* gsym,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type_1,
     unsigned int r_type_2)
 {
@@ -1500,10 +1500,11 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
 
   unsigned int got_offset = this->add_got_entry_pair(Got_entry(), Got_entry());
   gsym->set_got_offset(got_type, got_offset);
-  rela_dyn->add_global(gsym, r_type_1, this, got_offset, 0);
+  rel_dyn->add_global_generic(gsym, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rela_dyn->add_global(gsym, r_type_2, this, got_offset + size / 8, 0);
+    rel_dyn->add_global_generic(gsym, r_type_2, this,
+                               got_offset + size / 8, 0);
 }
 
 // Add an entry for a local symbol to the GOT.  This returns true if
@@ -1513,7 +1514,7 @@ Output_data_got<size, big_endian>::add_global_pair_with_rela(
 template<int size, bool big_endian>
 bool
 Output_data_got<size, big_endian>::add_local(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type)
 {
@@ -1531,7 +1532,7 @@ Output_data_got<size, big_endian>::add_local(
 template<int size, bool big_endian>
 bool
 Output_data_got<size, big_endian>::add_local_plt(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type)
 {
@@ -1550,10 +1551,10 @@ Output_data_got<size, big_endian>::add_local_plt(
 template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::add_local_with_rel(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type)
 {
   if (object->local_has_got_offset(symndx, got_type))
@@ -1561,24 +1562,7 @@ Output_data_got<size, big_endian>::add_local_with_rel(
 
   unsigned int got_offset = this->add_got_entry(Got_entry());
   object->set_local_got_offset(symndx, got_type, got_offset);
-  rel_dyn->add_local(object, symndx, r_type, this, got_offset);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_with_rela(
-    Sized_relobj_file<size, big_endian>* object,
-    unsigned int symndx,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
-    unsigned int r_type)
-{
-  if (object->local_has_got_offset(symndx, got_type))
-    return;
-
-  unsigned int got_offset = this->add_got_entry(Got_entry());
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  rela_dyn->add_local(object, symndx, r_type, this, got_offset, 0);
+  rel_dyn->add_local_generic(object, symndx, r_type, this, got_offset, 0);
 }
 
 // Add a pair of entries for a local symbol to the GOT, and add
@@ -1587,11 +1571,11 @@ Output_data_got<size, big_endian>::add_local_with_rela(
 template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::add_local_pair_with_rel(
-    Sized_relobj_file<size, big_endian>* object,
+    Relobj* object,
     unsigned int symndx,
     unsigned int shndx,
     unsigned int got_type,
-    Rel_dyn* rel_dyn,
+    Output_data_reloc_generic* rel_dyn,
     unsigned int r_type_1,
     unsigned int r_type_2)
 {
@@ -1603,35 +1587,11 @@ Output_data_got<size, big_endian>::add_local_pair_with_rel(
                               Got_entry(object, symndx, false));
   object->set_local_got_offset(symndx, got_type, got_offset);
   Output_section* os = object->output_section(shndx);
-  rel_dyn->add_output_section(os, r_type_1, this, got_offset);
+  rel_dyn->add_output_section_generic(os, r_type_1, this, got_offset, 0);
 
   if (r_type_2 != 0)
-    rel_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8);
-}
-
-template<int size, bool big_endian>
-void
-Output_data_got<size, big_endian>::add_local_pair_with_rela(
-    Sized_relobj_file<size, big_endian>* object,
-    unsigned int symndx,
-    unsigned int shndx,
-    unsigned int got_type,
-    Rela_dyn* rela_dyn,
-    unsigned int r_type_1,
-    unsigned int r_type_2)
-{
-  if (object->local_has_got_offset(symndx, got_type))
-    return;
-
-  unsigned int got_offset =
-      this->add_got_entry_pair(Got_entry(),
-                              Got_entry(object, symndx, false));
-  object->set_local_got_offset(symndx, got_type, got_offset);
-  Output_section* os = object->output_section(shndx);
-  rela_dyn->add_output_section(os, r_type_1, this, got_offset, 0);
-
-  if (r_type_2 != 0)
-    rela_dyn->add_output_section(os, r_type_2, this, got_offset + size / 8, 0);
+    rel_dyn->add_output_section_generic(os, r_type_2, this,
+                                       got_offset + size / 8, 0);
 }
 
 // Reserve a slot in the GOT for a local symbol or the second slot of a pair.
@@ -1640,11 +1600,11 @@ template<int size, bool big_endian>
 void
 Output_data_got<size, big_endian>::reserve_local(
     unsigned int i,
-    Sized_relobj<size, big_endian>* object,
+    Relobj* object,
     unsigned int sym_index,
     unsigned int got_type)
 {
-  this->reserve_slot(i);
+  this->do_reserve_slot(i);
   object->set_local_got_offset(sym_index, got_type, this->got_offset(i));
 }
 
@@ -1657,7 +1617,7 @@ Output_data_got<size, big_endian>::reserve_global(
     Symbol* gsym,
     unsigned int got_type)
 {
-  this->reserve_slot(i);
+  this->do_reserve_slot(i);
   gsym->set_got_offset(got_type, this->got_offset(i));
 }
 
@@ -1747,6 +1707,18 @@ Output_data_got<size, big_endian>::add_got_entry_pair(Got_entry got_entry_1,
     }
 }
 
+// Replace GOT entry I with a new value.
+
+template<int size, bool big_endian>
+void
+Output_data_got<size, big_endian>::replace_got_entry(
+    unsigned int i,
+    Got_entry got_entry)
+{
+  gold_assert(i < this->entries_.size());
+  this->entries_[i] = got_entry;
+}
+
 // Output_data_dynamic::Dynamic_entry methods.
 
 // Write out the entry.
@@ -1949,7 +1921,8 @@ Output_fill_debug_info::do_minimum_hole_size() const
 void
 Output_fill_debug_info::do_write(Output_file* of, off_t off, size_t len) const
 {
-  gold_debug(DEBUG_INCREMENTAL, "fill_debug_info(%08lx, %08lx)", off, len);
+  gold_debug(DEBUG_INCREMENTAL, "fill_debug_info(%08lx, %08lx)",
+            static_cast<long>(off), static_cast<long>(len));
 
   gold_assert(len >= this->do_minimum_hole_size());
 
@@ -1960,15 +1933,15 @@ Output_fill_debug_info::do_write(Output_file* of, off_t off, size_t len) const
   // address_size.
   if (this->is_big_endian())
     {
-      elfcpp::Swap<32, true>::writeval(pov, len - 4);
-      elfcpp::Swap<16, true>::writeval(pov + 4, this->version);
-      elfcpp::Swap<32, true>::writeval(pov + 6, 0);
+      elfcpp::Swap_unaligned<32, true>::writeval(pov, len - 4);
+      elfcpp::Swap_unaligned<16, true>::writeval(pov + 4, this->version);
+      elfcpp::Swap_unaligned<32, true>::writeval(pov + 6, 0);
     }
   else
     {
-      elfcpp::Swap<32, false>::writeval(pov, len - 4);
-      elfcpp::Swap<16, false>::writeval(pov + 4, this->version);
-      elfcpp::Swap<32, false>::writeval(pov + 6, 0);
+      elfcpp::Swap_unaligned<32, false>::writeval(pov, len - 4);
+      elfcpp::Swap_unaligned<16, false>::writeval(pov + 4, this->version);
+      elfcpp::Swap_unaligned<32, false>::writeval(pov + 6, 0);
     }
   pov += 4 + 2 + 4;
   *pov++ = 4;
@@ -2005,7 +1978,8 @@ Output_fill_debug_line::do_minimum_hole_size() const
 void
 Output_fill_debug_line::do_write(Output_file* of, off_t off, size_t len) const
 {
-  gold_debug(DEBUG_INCREMENTAL, "fill_debug_line(%08lx, %08lx)", off, len);
+  gold_debug(DEBUG_INCREMENTAL, "fill_debug_line(%08lx, %08lx)",
+            static_cast<long>(off), static_cast<long>(len));
 
   gold_assert(len >= this->do_minimum_hole_size());
 
@@ -2019,15 +1993,15 @@ Output_fill_debug_line::do_write(Output_file* of, off_t off, size_t len) const
   // line number program is empty.
   if (this->is_big_endian())
     {
-      elfcpp::Swap<32, true>::writeval(pov, len - 4);
-      elfcpp::Swap<16, true>::writeval(pov + 4, this->version);
-      elfcpp::Swap<32, true>::writeval(pov + 6, len - (4 + 2 + 4));
+      elfcpp::Swap_unaligned<32, true>::writeval(pov, len - 4);
+      elfcpp::Swap_unaligned<16, true>::writeval(pov + 4, this->version);
+      elfcpp::Swap_unaligned<32, true>::writeval(pov + 6, len - (4 + 2 + 4));
     }
   else
     {
-      elfcpp::Swap<32, false>::writeval(pov, len - 4);
-      elfcpp::Swap<16, false>::writeval(pov + 4, this->version);
-      elfcpp::Swap<32, false>::writeval(pov + 6, len - (4 + 2 + 4));
+      elfcpp::Swap_unaligned<32, false>::writeval(pov, len - 4);
+      elfcpp::Swap_unaligned<16, false>::writeval(pov + 4, this->version);
+      elfcpp::Swap_unaligned<32, false>::writeval(pov + 6, len - (4 + 2 + 4));
     }
   pov += 4 + 2 + 4;
   *pov++ = 1;  // minimum_instruction_length
@@ -2289,7 +2263,10 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
     always_keeps_input_sections_(false),
     has_fixed_layout_(false),
     is_patch_space_allowed_(false),
+    is_unique_segment_(false),
     tls_offset_(0),
+    extra_segment_flags_(0),
+    segment_alignment_(0),
     checkpoint_(NULL),
     lookup_maps_(new Output_section_lookup_maps),
     free_list_(),
@@ -2474,7 +2451,10 @@ Output_section::add_input_section(Layout* layout,
       || layout->is_section_ordering_specified())
     {
       Input_section isecn(object, shndx, input_section_size, addralign);
-      if (layout->is_section_ordering_specified())
+      /* If section ordering is requested by specifying a ordering file,
+        using --section-ordering-file, match the section name with
+        a pattern.  */
+      if (parameters->options().section_ordering_file())
         {
           unsigned int section_order_index =
             layout->find_section_order_index(std::string(secname));
@@ -3483,7 +3463,7 @@ Output_section::Input_section_sort_section_order_index_compare::operator()(
 
 void
 Output_section::update_section_layout(
-  const Section_layout_order& order_map)
+  const Section_layout_order* order_map)
 {
   for (Input_section_list::iterator p = this->input_sections_.begin();
        p != this->input_sections_.end();
@@ -3497,8 +3477,8 @@ Output_section::update_section_layout(
                         : p->relaxed_input_section()->relobj());
          unsigned int shndx = p->shndx();
          Section_layout_order::const_iterator it
-           = order_map.find(Section_id(obj, shndx));
-         if (it == order_map.end())
+           = order_map->find(Section_id(obj, shndx));
+         if (it == order_map->end())
            continue;
          unsigned int section_order_index = it->second;
          if (section_order_index != 0)
@@ -4020,7 +4000,8 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
     flags_(flags),
     is_max_align_known_(false),
     are_addresses_set_(false),
-    is_large_data_segment_(false)
+    is_large_data_segment_(false),
+    is_unique_segment_(false)
 {
   // The ELF ABI specifies that a PT_TLS segment always has PF_R as
   // the flags.
@@ -4632,10 +4613,10 @@ Output_segment::set_tls_offsets()
     (*p)->set_tls_offset(this->vaddr_);
 }
 
-// Return the load address of the first section.
+// Return the first section.
 
-uint64_t
-Output_segment::first_section_load_address() const
+Output_section*
+Output_segment::first_section() const
 {
   for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
     {
@@ -4645,9 +4626,7 @@ Output_segment::first_section_load_address() const
           ++p)
        {
          if ((*p)->is_section())
-           return ((*p)->has_load_address()
-                   ? (*p)->load_address()
-                   : (*p)->address());
+           return (*p)->output_section();
        }
     }
   gold_unreachable();
@@ -4878,17 +4857,27 @@ Output_file::open_base_file(const char* base_name, bool writable)
   if (use_base_file)
     {
       this->open(s.st_size);
-      ssize_t len = ::read(o, this->base_, s.st_size);
-      if (len < 0)
-        {
-         gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
-         return false;
-        }
-      if (len < s.st_size)
-        {
-         gold_info(_("%s: file too short"), base_name);
-         return false;
-        }
+      ssize_t bytes_to_read = s.st_size;
+      unsigned char* p = this->base_;
+      while (bytes_to_read > 0)
+       {
+         ssize_t len = ::read(o, p, bytes_to_read);
+         if (len < 0)
+           {
+             gold_info(_("%s: read failed: %s"), base_name, strerror(errno));
+             return false;
+           }
+         if (len == 0)
+           {
+             gold_info(_("%s: file too short: read only %lld of %lld bytes"),
+                       base_name,
+                       static_cast<long long>(s.st_size - bytes_to_read),
+                       static_cast<long long>(s.st_size));
+             return false;
+           }
+         p += len;
+         bytes_to_read -= len;
+       }
       ::close(o);
       return true;
     }
@@ -5050,8 +5039,12 @@ Output_file::map_no_anonymous(bool writable)
   // output file will wind up incomplete, but we will have already
   // exited.  The alternative to fallocate would be to use fdatasync,
   // but that would be a more significant performance hit.
-  if (writable && ::posix_fallocate(o, 0, this->file_size_) < 0)
-    gold_fatal(_("%s: %s"), this->name_, strerror(errno));
+  if (writable)
+    {
+      int err = gold_fallocate(o, 0, this->file_size_);
+      if (err != 0)
+       gold_fatal(_("%s: %s"), this->name_, strerror(err));
+    }
 
   // Map the file into memory.
   int prot = PROT_READ;
@@ -5075,7 +5068,8 @@ Output_file::map_no_anonymous(bool writable)
 void
 Output_file::map()
 {
-  if (this->map_no_anonymous(true))
+  if (parameters->options().mmap_output_file()
+      && this->map_no_anonymous(true))
     return;
 
   // The mmap call might fail because of file system issues: the file
This page took 0.031525 seconds and 4 git commands to generate.