2008-07-11 H.J. Lu <hongjiu.lu@intel.com>
[deliverable/binutils-gdb.git] / gold / output.h
index 7c24372fed8150796163e96645817ebc223ab548..e2c41c7d7da74cecfda02676ff72a330b97ea4be 100644 (file)
@@ -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.
@@ -397,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>
@@ -428,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>
@@ -462,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>
@@ -663,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_;
 };
@@ -674,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:
@@ -688,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
@@ -698,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:
@@ -708,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
@@ -716,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.
@@ -731,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.
@@ -757,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_;
 };
@@ -798,7 +890,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.
@@ -818,7 +911,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.
@@ -839,7 +933,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
@@ -912,7 +1006,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.
@@ -961,7 +1055,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)
@@ -994,7 +1089,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)
   { }
@@ -1056,6 +1152,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)
@@ -1113,7 +1219,8 @@ 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)); }
@@ -1129,7 +1236,8 @@ class Output_data_reloc<elfcpp::SHT_REL, dynamic, size, big_endian>
   }
 
   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, Address addend)
   {
     gold_assert(addend == 0);
@@ -1146,7 +1254,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));
@@ -1225,7 +1334,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)); }
 };
 
@@ -1257,7 +1367,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,
@@ -1275,8 +1386,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)); }
 
@@ -1353,7 +1464,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)); }
@@ -1380,6 +1492,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_;
@@ -1400,6 +1517,11 @@ class Output_data_group : 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, _("** group")); }
+
  private:
   // The input object.
   Sized_relobj<size, big_endian>* relobj_;
@@ -1502,6 +1624,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
@@ -1639,6 +1766,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
@@ -1752,6 +1884,11 @@ class Output_symtab_xindex : 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, _("** symtab xindex")); }
+
  private:
   template<bool big_endian>
   void
@@ -2028,6 +2165,29 @@ 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; }
+
+  // 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
@@ -2239,6 +2399,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
@@ -2289,8 +2453,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;
@@ -2301,7 +2464,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;
@@ -2311,6 +2474,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));
@@ -2416,6 +2581,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)
@@ -2626,6 +2795,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_;
@@ -2682,13 +2855,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.
@@ -2781,26 +2948,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
@@ -2824,6 +2994,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.
This page took 0.029608 seconds and 4 git commands to generate.