Remove a white space.
[deliverable/binutils-gdb.git] / gold / output.h
index 81685e2cb343f391d3670474158208775c887fb2..5d2c62f3e3c28a0aba9095c14bc670ee5166c519 100644 (file)
@@ -1,6 +1,6 @@
 // output.h -- manage the output file for gold   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -27,6 +27,7 @@
 #include <vector>
 
 #include "elfcpp.h"
+#include "mapfile.h"
 #include "layout.h"
 #include "reloc-types.h"
 
@@ -240,6 +241,11 @@ class Output_data
   is_data_size_valid() const
   { return this->is_data_size_valid_; }
 
+  // Print information to the map file.
+  void
+  print_to_mapfile(Mapfile* mapfile) const
+  { return this->do_print_to_mapfile(mapfile); }
+
  protected:
   // Functions that child classes may or in some cases must implement.
 
@@ -316,6 +322,12 @@ class Output_data
   do_tls_offset() const
   { gold_unreachable(); }
 
+  // Print to the map file.  This only needs to be implemented by
+  // classes which may appear in a PT_LOAD segment.
+  virtual void
+  do_print_to_mapfile(Mapfile*) const
+  { gold_unreachable(); }
+
   // Functions that child classes may call.
 
   // Set the size of the data.
@@ -384,7 +396,8 @@ class Output_section_headers : public Output_data
                         const Layout::Segment_list*,
                         const Layout::Section_list*,
                         const Layout::Section_list*,
-                        const Stringpool*);
+                        const Stringpool*,
+                        const Output_section*);
 
  protected:
   // Write the data to the file.
@@ -396,6 +409,11 @@ class Output_section_headers : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** section headers")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -407,6 +425,7 @@ class Output_section_headers : public Output_data
   const Layout::Section_list* section_list_;
   const Layout::Section_list* unattached_section_list_;
   const Stringpool* secnamepool_;
+  const Output_section* shstrtab_section_;
 };
 
 // Output the segment headers.
@@ -426,6 +445,11 @@ class Output_segment_headers : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** segment headers")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -460,6 +484,11 @@ class Output_file_header : public Output_data
   do_addralign() const
   { return Output_data::default_alignment(); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** file header")); }
+
  private:
   // Write the data to the file with the right size and endianness.
   template<int size, bool big_endian>
@@ -661,6 +690,11 @@ class Output_data_const : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { memcpy(buffer, this->data_.data(), this->data_.size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** fill")); }
+
  private:
   std::string data_;
 };
@@ -672,8 +706,9 @@ class Output_data_const_buffer : public Output_section_data
 {
  public:
   Output_data_const_buffer(const unsigned char* p, off_t len,
-                          uint64_t addralign)
-    : Output_section_data(len, addralign), p_(p)
+                          uint64_t addralign, const char* map_name)
+    : Output_section_data(len, addralign),
+      p_(p), map_name_(map_name)
   { }
 
  protected:
@@ -686,8 +721,17 @@ class Output_data_const_buffer : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { memcpy(buffer, this->p_, this->data_size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
  private:
+  // The data to output.
   const unsigned char* p_;
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
 };
 
 // A place holder for a fixed amount of data written out via some
@@ -696,8 +740,10 @@ class Output_data_const_buffer : public Output_section_data
 class Output_data_fixed_space : public Output_section_data
 {
  public:
-  Output_data_fixed_space(off_t data_size, uint64_t addralign)
-    : Output_section_data(data_size, addralign)
+  Output_data_fixed_space(off_t data_size, uint64_t addralign,
+                         const char* map_name)
+    : Output_section_data(data_size, addralign),
+      map_name_(map_name)
   { }
 
  protected:
@@ -706,6 +752,16 @@ class Output_data_fixed_space : public Output_section_data
   void
   do_write(Output_file*)
   { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
+ private:
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
 };
 
 // A place holder for variable sized data written out via some other
@@ -714,8 +770,9 @@ class Output_data_fixed_space : public Output_section_data
 class Output_data_space : public Output_section_data_build
 {
  public:
-  explicit Output_data_space(uint64_t addralign)
-    : Output_section_data_build(addralign)
+  explicit Output_data_space(uint64_t addralign, const char* map_name)
+    : Output_section_data_build(addralign),
+      map_name_(map_name)
   { }
 
   // Set the alignment.
@@ -729,6 +786,38 @@ class Output_data_space : public Output_section_data_build
   void
   do_write(Output_file*)
   { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _(this->map_name_)); }
+
+ private:
+  // Name to use in a map file.  Maps are a rarely used feature, but
+  // the space usage is minor as aren't very many of these objects.
+  const char* map_name_;
+};
+
+// Fill fixed space with zeroes.  This is just like
+// Output_data_fixed_space, except that the map name is known.
+
+class Output_data_zero_fill : public Output_section_data
+{
+ public:
+  Output_data_zero_fill(off_t data_size, uint64_t addralign)
+    : Output_section_data(data_size, addralign)
+  { }
+
+ protected:
+  // There is no data to write out.
+  void
+  do_write(Output_file*)
+  { }
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, "** zero fill"); }
 };
 
 // A string table which goes into an output section.
@@ -755,6 +844,11 @@ class Output_data_strtab : public Output_section_data
   do_write_to_buffer(unsigned char* buffer)
   { this->strtab_->write_to_buffer(buffer, this->data_size()); }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** string table")); }
+
  private:
   Stringpool* strtab_;
 };
@@ -780,6 +874,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
 
+  static const Address invalid_address = static_cast<Address>(0) - 1;
+
   // An uninitialized entry.  We need this because we want to put
   // instances of this class into an STL container.
   Output_reloc()
@@ -796,7 +892,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Output_reloc(Symbol* gsym, unsigned int type, Output_data* od,
               Address address, bool is_relative);
 
-  Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+  Output_reloc(Symbol* gsym, unsigned int type,
+               Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address, bool is_relative);
 
   // A reloc against a local symbol or local section symbol.
@@ -816,7 +913,8 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   Output_reloc(Output_section* os, unsigned int type, Output_data* od,
               Address address);
 
-  Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+  Output_reloc(Output_section* os, unsigned int type,
+               Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address);
 
   // Return TRUE if this is a RELATIVE relocation.
@@ -837,7 +935,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   // For a local section symbol, return the offset of the input
   // section within the output section.  ADDEND is the addend being
   // applied to the input section.
-  section_offset_type
+  Address
   local_section_offset(Addend addend) const;
 
   // Get the value of the symbol referred to by a Rel relocation when
@@ -853,6 +951,19 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   template<typename Write_rel>
   void write_rel(Write_rel*) const;
 
+  // This is used when sorting dynamic relocs.  Return -1 to sort this
+  // reloc before R2, 0 to sort the same as R2, 1 to sort after R2.
+  int
+  compare(const Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>& r2)
+    const;
+
+  // Return whether this reloc should be sorted before the argument
+  // when sorting dynamic relocs.
+  bool
+  sort_before(const Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>&
+             r2) const
+  { return this->compare(r2) < 0; }
+
  private:
   // Record that we need a dynamic symbol index.
   void
@@ -862,6 +973,10 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   unsigned int
   get_symbol_index() const;
 
+  // Return the output address.
+  Address
+  get_address() const;
+
   // Codes for local_sym_index_.
   enum
   {
@@ -893,7 +1008,7 @@ class Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   {
     // If this->shndx_ is not INVALID CODE, the object which holds the
     // input section being used to specify the reloc address.
-    Relobj* relobj;
+    Sized_relobj<size, big_endian>* relobj;
     // If this->shndx_ is INVALID_CODE, the output data being used to
     // specify the reloc address.  This may be NULL if the reloc
     // address is absolute.
@@ -942,7 +1057,8 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     : rel_(gsym, type, od, address, is_relative), addend_(addend)
   { }
 
-  Output_reloc(Symbol* gsym, unsigned int type, Relobj* relobj,
+  Output_reloc(Symbol* gsym, unsigned int type,
+               Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address, Addend addend,
               bool is_relative)
     : rel_(gsym, type, relobj, shndx, address, is_relative), addend_(addend)
@@ -975,7 +1091,8 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
     : rel_(os, type, od, address), addend_(addend)
   { }
 
-  Output_reloc(Output_section* os, unsigned int type, Relobj* relobj,
+  Output_reloc(Output_section* os, unsigned int type,
+               Sized_relobj<size, big_endian>* relobj,
               unsigned int shndx, Address address, Addend addend)
     : rel_(os, type, relobj, shndx, address), addend_(addend)
   { }
@@ -984,6 +1101,21 @@ class Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   void
   write(unsigned char* pov) const;
 
+  // Return whether this reloc should be sorted before the argument
+  // when sorting dynamic relocs.
+  bool
+  sort_before(const Output_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>&
+             r2) const
+  {
+    int i = this->rel_.compare(r2.rel_);
+    if (i < 0)
+      return true;
+    else if (i > 0)
+      return false;
+    else
+      return this->addend_ < r2.addend_;
+  }
+
  private:
   // The basic reloc.
   Output_reloc<elfcpp::SHT_REL, dynamic, size, big_endian> rel_;
@@ -1008,8 +1140,9 @@ class Output_data_reloc_base : public Output_section_data_build
     Reloc_types<sh_type, size, big_endian>::reloc_size;
 
   // Construct the section.
-  Output_data_reloc_base()
-    : Output_section_data_build(Output_data::default_alignment_for_size(size))
+  Output_data_reloc_base(bool sort_relocs)
+    : Output_section_data_build(Output_data::default_alignment_for_size(size)),
+      sort_relocs_(sort_relocs)
   { }
 
  protected:
@@ -1021,6 +1154,16 @@ class Output_data_reloc_base : public Output_section_data_build
   void
   do_adjust_output_section(Output_section *os);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  {
+    mapfile->print_output_data(this,
+                              (dynamic
+                               ? _("** dynamic relocs")
+                               : _("** relocs")));
+  }
+
   // Add a relocation entry.
   void
   add(Output_data *od, const Output_reloc_type& reloc)
@@ -1033,7 +1176,19 @@ class Output_data_reloc_base : public Output_section_data_build
  private:
   typedef std::vector<Output_reloc_type> Relocs;
 
+  // The class used to sort the relocations.
+  struct Sort_relocs_comparison
+  {
+    bool
+    operator()(const Output_reloc_type& r1, const Output_reloc_type& r2) const
+    { return r1.sort_before(r2); }
+  };
+
+  // The relocations in this section.
   Relocs relocs_;
+  // Whether to sort the relocations when writing them out, to make
+  // the dynamic linker more efficient.
+  bool sort_relocs_;
 };
 
 // The class which callers actually create.
@@ -1055,8 +1210,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   typedef typename Base::Output_reloc_type Output_reloc_type;
   typedef typename Output_reloc_type::Address Address;
 
-  Output_data_reloc()
-    : Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>()
+  Output_data_reloc(bool sr)
+    : Output_data_reloc_base<elfcpp::SHT_REL, dynamic, size, big_endian>(sr)
   { }
 
   // Add a reloc against a global symbol.
@@ -1066,11 +1221,31 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   { this->add(od, Output_reloc_type(gsym, type, od, address, false)); }
 
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
+  add_global(Symbol* gsym, unsigned int type, Output_data* od,
+             Sized_relobj<size, big_endian>* relobj,
             unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     false)); }
 
+  // These are to simplify the Copy_relocs class.
+
+  void
+  add_global(Symbol* gsym, unsigned int type, Output_data* od, Address address,
+            Address addend)
+  {
+    gold_assert(addend == 0);
+    this->add_global(gsym, type, od, address);
+  }
+
+  void
+  add_global(Symbol* gsym, unsigned int type, Output_data* od,
+             Sized_relobj<size, big_endian>* relobj,
+            unsigned int shndx, Address address, Address addend)
+  {
+    gold_assert(addend == 0);
+    this->add_global(gsym, type, od, relobj, shndx, address);
+  }
+
   // Add a RELATIVE reloc against a global symbol.  The final relocation
   // will not reference the symbol.
 
@@ -1081,7 +1256,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                      Relobj* relobj, unsigned int shndx, Address address)
+                      Sized_relobj<size, big_endian>* relobj,
+                      unsigned int shndx, Address address)
   {
     this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     true));
@@ -1160,7 +1336,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
 
   void
   add_output_section(Output_section* os, unsigned int type, Output_data* od,
-                    Relobj* relobj, unsigned int shndx, Address address)
+                    Sized_relobj<size, big_endian>* relobj,
+                     unsigned int shndx, Address address)
   { this->add(od, Output_reloc_type(os, type, relobj, shndx, address)); }
 };
 
@@ -1179,8 +1356,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   typedef typename Output_reloc_type::Address Address;
   typedef typename Output_reloc_type::Addend Addend;
 
-  Output_data_reloc()
-    : Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>()
+  Output_data_reloc(bool sr)
+    : Output_data_reloc_base<elfcpp::SHT_RELA, dynamic, size, big_endian>(sr)
   { }
 
   // Add a reloc against a global symbol.
@@ -1192,7 +1369,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
                                     false)); }
 
   void
-  add_global(Symbol* gsym, unsigned int type, Output_data* od, Relobj* relobj,
+  add_global(Symbol* gsym, unsigned int type, Output_data* od,
+             Sized_relobj<size, big_endian>* relobj,
             unsigned int shndx, Address address,
             Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
@@ -1210,8 +1388,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
 
   void
   add_global_relative(Symbol* gsym, unsigned int type, Output_data* od,
-                      Relobj* relobj, unsigned int shndx, Address address,
-                     Addend addend)
+                      Sized_relobj<size, big_endian>* relobj,
+                      unsigned int shndx, Address address, Addend addend)
   { this->add(od, Output_reloc_type(gsym, type, relobj, shndx, address,
                                     addend, true)); }
 
@@ -1288,7 +1466,8 @@ class Output_data_reloc<elfcpp::SHT_RELA, dynamic, size, big_endian>
   { this->add(os, Output_reloc_type(os, type, od, address, addend)); }
 
   void
-  add_output_section(Output_section* os, unsigned int type, Relobj* relobj,
+  add_output_section(Output_section* os, unsigned int type,
+                     Sized_relobj<size, big_endian>* relobj,
                     unsigned int shndx, Address address, Addend addend)
   { this->add(os, Output_reloc_type(os, type, relobj, shndx, address,
                                     addend)); }
@@ -1315,6 +1494,11 @@ class Output_relocatable_relocs : public Output_section_data
   do_write(Output_file*)
   { }
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** relocs")); }
+
  private:
   // The relocs associated with this input section.
   Relocatable_relocs* rr_;
@@ -1326,20 +1510,27 @@ template<int size, bool big_endian>
 class Output_data_group : public Output_section_data
 {
  public:
+  // The constructor clears *INPUT_SHNDXES.
   Output_data_group(Sized_relobj<size, big_endian>* relobj,
                    section_size_type entry_count,
-                   const elfcpp::Elf_Word* contents);
+                   elfcpp::Elf_Word flags,
+                   std::vector<unsigned int>* input_shndxes);
 
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** group")); }
+
  private:
   // The input object.
   Sized_relobj<size, big_endian>* relobj_;
   // The group flag word.
   elfcpp::Elf_Word flags_;
   // The section indexes of the input sections in this group.
-  std::vector<unsigned int> input_sections_;
+  std::vector<unsigned int> input_shndxes_;
 };
 
 // Output_data_got is used to manage a GOT.  Each entry in the GOT is
@@ -1435,6 +1626,11 @@ class Output_data_got : public Output_section_data_build
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** GOT")); }
+
  private:
   // This POD class holds a single GOT entry.
   class Got_entry
@@ -1572,6 +1768,11 @@ class Output_data_dynamic : public Output_section_data
   void
   do_write(Output_file*);
 
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** dynamic")); }
+
  private:
   // This POD class holds a single dynamic entry.
   class Dynamic_entry
@@ -1664,6 +1865,46 @@ class Output_data_dynamic : public Output_section_data
   Stringpool* pool_;
 };
 
+// Output_symtab_xindex is used to handle SHT_SYMTAB_SHNDX sections,
+// which may be required if the object file has more than
+// SHN_LORESERVE sections.
+
+class Output_symtab_xindex : public Output_section_data
+{
+ public:
+  Output_symtab_xindex(size_t symcount)
+    : Output_section_data(symcount * 4, 4),
+      entries_()
+  { }
+
+  // Add an entry: symbol number SYMNDX has section SHNDX.
+  void
+  add(unsigned int symndx, unsigned int shndx)
+  { this->entries_.push_back(std::make_pair(symndx, shndx)); }
+
+ protected:
+  void
+  do_write(Output_file*);
+
+  // Write to a map file.
+  void
+  do_print_to_mapfile(Mapfile* mapfile) const
+  { mapfile->print_output_data(this, _("** symtab xindex")); }
+
+ private:
+  template<bool big_endian>
+  void
+  endian_do_write(unsigned char*);
+
+  // It is likely that most symbols will not require entries.  Rather
+  // than keep a vector for all symbols, we keep pairs of symbol index
+  // and section index.
+  typedef std::vector<std::pair<unsigned int, unsigned int> > Xindex_entries;
+
+  // The entries we need.
+  Xindex_entries entries_;
+};
+
 // An output section.  We don't expect to have too many output
 // sections, so we don't bother to do a template on the size.
 
@@ -1676,7 +1917,7 @@ class Output_section : public Output_data
 
   // Add a new input section SHNDX, named NAME, with header SHDR, from
   // object OBJECT.  RELOC_SHNDX is the index of a relocation section
-  // which applies to this section, or 0 if none, or -1U if more than
+  // which applies to this section, or 0 if none, or -1 if more than
   // one.  HAVE_SECTIONS_SCRIPT is true if we have a SECTIONS clause
   // in a linker script; in that case we need to keep track of input
   // sections associated with an output section.  Return the offset
@@ -1843,6 +2084,11 @@ class Output_section : public Output_data
   set_addralign(uint64_t v)
   { this->addralign_ = v; }
 
+  // Whether the output section index has been set.
+  bool
+  has_out_shndx() const
+  { return this->out_shndx_ != -1U; }
+
   // Indicate that we need a symtab index.
   void
   set_needs_symtab_index()
@@ -1921,6 +2167,34 @@ class Output_section : public Output_data
   set_must_sort_attached_input_sections()
   { this->must_sort_attached_input_sections_ = true; }
 
+  // Return whether this section holds relro data--data which has
+  // dynamic relocations but which may be marked read-only after the
+  // dynamic relocations have been completed.
+  bool
+  is_relro() const
+  { return this->is_relro_; }
+
+  // Record that this section holds relro data.
+  void
+  set_is_relro()
+  { this->is_relro_ = true; }
+
+  // Record that this section does not hold relro data.
+  void
+  clear_is_relro()
+  { this->is_relro_ = false; }
+
+  // True if this section holds relro local data--relro data for which
+  // the dynamic relocations are all RELATIVE relocations.
+  bool
+  is_relro_local() const
+  { return this->is_relro_local_; }
+
+  // Record that this section holds relro local data.
+  void
+  set_is_relro_local()
+  { this->is_relro_local_ = true; }
+
   // Return whether this section should be written after all the input
   // sections are complete.
   bool
@@ -1986,12 +2260,14 @@ class Output_section : public Output_data
   output_address(const Relobj* object, unsigned int shndx,
                 off_t offset) const;
 
-  // Return the output address of the start of the merged section for
-  // input section SHNDX in object OBJECT.  This is not necessarily
-  // the offset corresponding to input offset 0 in the section, since
-  // the section may be mapped arbitrarily.
-  uint64_t
-  starting_output_address(const Relobj* object, unsigned int shndx) const;
+  // Look for the merged section for input section SHNDX in object
+  // OBJECT.  If found, return true, and set *ADDR to the address of
+  // the start of the merged section.  This is not necessary the
+  // output offset corresponding to input offset 0 in the section,
+  // since the section may be mapped arbitrarily.
+  bool
+  find_starting_output_address(const Relobj* object, unsigned int shndx,
+                              uint64_t* addr) const;
 
   // Record that this output section was found in the SECTIONS clause
   // of a linker script.
@@ -2132,6 +2408,10 @@ class Output_section : public Output_data
   do_finalize_name(Layout*)
   { }
 
+  // Print to the map file.
+  virtual void
+  do_print_to_mapfile(Mapfile*) const;
+
   // Record that this section requires postprocessing after all
   // relocations have been applied.  This is called by a child class.
   void
@@ -2182,8 +2462,7 @@ class Output_section : public Output_data
 
     // For a non-merge output section.
     Input_section(Output_section_data* posd)
-      : shndx_(OUTPUT_SECTION_CODE),
-       p2align_(ffsll(static_cast<long long>(posd->addralign())))
+      : shndx_(OUTPUT_SECTION_CODE), p2align_(0)
     {
       this->u1_.data_size = 0;
       this->u2_.posd = posd;
@@ -2194,7 +2473,7 @@ class Output_section : public Output_data
       : shndx_(is_string
               ? MERGE_STRING_SECTION_CODE
               : MERGE_DATA_SECTION_CODE),
-       p2align_(ffsll(static_cast<long long>(posd->addralign())))
+       p2align_(0)
     {
       this->u1_.entsize = entsize;
       this->u2_.posd = posd;
@@ -2204,6 +2483,8 @@ class Output_section : public Output_data
     uint64_t
     addralign() const
     {
+      if (!this->is_input_section())
+       return this->u2_.posd->addralign();
       return (this->p2align_ == 0
              ? 0
              : static_cast<uint64_t>(1) << (this->p2align_ - 1));
@@ -2309,6 +2590,10 @@ class Output_section : public Output_data
     void
     write_to_buffer(unsigned char*);
 
+    // Print to a map file.
+    void
+    print_to_mapfile(Mapfile*) const;
+
     // Print statistics about merge sections to stderr.
     void
     print_merge_stats(const char* section_name)
@@ -2519,6 +2804,10 @@ class Output_section : public Output_data
   // True if the input sections attached to this output section have
   // already been sorted.
   bool attached_input_sections_are_sorted_ : 1;
+  // True if this section holds relro data.
+  bool is_relro_ : 1;
+  // True if this section holds relro local data.
+  bool is_relro_local_ : 1;
   // For SHT_TLS sections, the offset of this section relative to the base
   // of the TLS segment.
   uint64_t tls_offset_;
@@ -2575,13 +2864,7 @@ class Output_segment
 
   // Add an Output_section to this segment.
   void
-  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags)
-  { this->add_output_section(os, seg_flags, false); }
-
-  // Add an Output_section to the start of this segment.
-  void
-  add_initial_output_section(Output_section* os, elfcpp::Elf_Word seg_flags)
-  { this->add_output_section(os, seg_flags, true); }
+  add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags);
 
   // Remove an Output_section from this segment.  It is an error if it
   // is not present.
@@ -2674,26 +2957,29 @@ class Output_segment
   write_section_headers(const Layout*, const Stringpool*, unsigned char* v,
                        unsigned int* pshndx) const;
 
+  // Print the output sections in the map file.
+  void
+  print_sections_to_mapfile(Mapfile*) const;
+
  private:
   Output_segment(const Output_segment&);
   Output_segment& operator=(const Output_segment&);
 
   typedef std::list<Output_data*> Output_data_list;
 
-  // Add an Output_section to this segment, specifying front or back.
-  void
-  add_output_section(Output_section*, elfcpp::Elf_Word seg_flags,
-                    bool front);
-
   // Find the maximum alignment in an Output_data_list.
   static uint64_t
   maximum_alignment_list(const Output_data_list*);
 
+  // Return whether the first data section is a relro section.
+  bool
+  is_first_section_relro() const;
+
   // Set the section addresses in an Output_data_list.
   uint64_t
   set_section_list_addresses(const Layout*, bool reset, Output_data_list*,
                              uint64_t addr, off_t* poff, unsigned int* pshndx,
-                             bool* in_tls);
+                             bool* in_tls, bool* in_relro);
 
   // Return the number of Output_sections in an Output_data_list.
   unsigned int
@@ -2717,6 +3003,10 @@ class Output_segment
                             const Output_data_list*, unsigned char* v,
                             unsigned int* pshdx) const;
 
+  // Print a section list to the mapfile.
+  void
+  print_section_list_to_mapfile(Mapfile*, const Output_data_list*) const;
+
   // The list of output data with contents attached to this segment.
   Output_data_list output_data_;
   // The list of output data without contents attached to this segment.
@@ -2825,10 +3115,14 @@ class Output_file
   { }
 
  private:
-  // Map the file into memory and return a pointer to the map.
+  // Map the file into memory.
   void
   map();
 
+  // Allocate anonymous memory for the file.
+  void*
+  map_anonymous();
+
   // Unmap the file from memory (and flush to disk buffers).
   void
   unmap();
This page took 0.033956 seconds and 4 git commands to generate.