OSDN Git Service

PR 10979
[pf3gnuchains/pf3gnuchains3x.git] / gold / layout.h
index 010ab2e..604f19b 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <cstring>
 #include <list>
+#include <map>
 #include <string>
 #include <utility>
 #include <vector>
@@ -39,12 +40,15 @@ namespace gold
 {
 
 class General_options;
+class Incremental_inputs;
 class Input_objects;
 class Mapfile;
 class Symbol_table;
 class Output_section_data;
 class Output_section;
 class Output_section_headers;
+class Output_segment_headers;
+class Output_file_header;
 class Output_segment;
 class Output_data;
 class Output_data_dynamic;
@@ -89,35 +93,192 @@ class Layout_task_runner : public Task_function_runner
   Mapfile* mapfile_;
 };
 
-// This struct holds information about the comdat or .gnu.linkonce
-// that will be kept.
+// This class holds information about the comdat group or
+// .gnu.linkonce section that will be kept for a given signature.
 
-struct Kept_section
+class Kept_section
 {
+ private:
+  // For a comdat group, we build a mapping from the name of each
+  // section in the group to the section index and the size in object.
+  // When we discard a group in some other object file, we use this
+  // map to figure out which kept section the discarded section is
+  // associated with.  We then use that mapping when processing relocs
+  // against discarded sections.
+  struct Comdat_section_info
+  {
+    // The section index.
+    unsigned int shndx;
+    // The section size.
+    uint64_t size;
+
+    Comdat_section_info(unsigned int a_shndx, uint64_t a_size)
+      : shndx(a_shndx), size(a_size)
+    { }
+  };
+
+  // Most comdat groups have only one or two sections, so we use a
+  // std::map rather than an Unordered_map to optimize for that case
+  // without paying too heavily for groups with more sections.
+  typedef std::map<std::string, Comdat_section_info> Comdat_group;
+
+ public:
   Kept_section()
-    : object(NULL), shndx(0), is_group(false), group_sections(NULL)
-  { }
-  Kept_section(Relobj* a_object, unsigned int a_shndx, bool a_is_group)
-    : object(a_object), shndx(a_shndx), is_group(a_is_group),
-      group_sections(NULL)
-  { }
+    : object_(NULL), shndx_(0), is_comdat_(false), is_group_name_(false)
+  { this->u_.linkonce_size = 0; }
+
+  // We need to support copies for the signature map in the Layout
+  // object, but we should never copy an object after it has been
+  // marked as a comdat section.
+  Kept_section(const Kept_section& k)
+    : object_(k.object_), shndx_(k.shndx_), is_comdat_(false),
+      is_group_name_(k.is_group_name_)
+  {
+    gold_assert(!k.is_comdat_);
+    this->u_.linkonce_size = 0;
+  }
+
+  ~Kept_section()
+  {
+    if (this->is_comdat_)
+      delete this->u_.group_sections;
+  }
+
+  // The object where this section lives.
+  Relobj*
+  object() const
+  { return this->object_; }
+
+  // Set the object.
+  void
+  set_object(Relobj* object)
+  {
+    gold_assert(this->object_ == NULL);
+    this->object_ = object;
+  }
+
+  // The section index.
+  unsigned int
+  shndx() const
+  { return this->shndx_; }
+
+  // Set the section index.
+  void
+  set_shndx(unsigned int shndx)
+  {
+    gold_assert(this->shndx_ == 0);
+    this->shndx_ = shndx;
+  }
+
+  // Whether this is a comdat group.
+  bool
+  is_comdat() const
+  { return this->is_comdat_; }
+
+  // Set that this is a comdat group.
+  void
+  set_is_comdat()
+  {
+    gold_assert(!this->is_comdat_);
+    this->is_comdat_ = true;
+    this->u_.group_sections = new Comdat_group();
+  }
+
+  // Whether this is associated with the name of a group or section
+  // rather than the symbol name derived from a linkonce section.
+  bool
+  is_group_name() const
+  { return this->is_group_name_; }
+
+  // Note that this represents a comdat group rather than a single
+  // linkonce section.
+  void
+  set_is_group_name()
+  { this->is_group_name_ = true; }
+
+  // Add a section to the group list.
+  void
+  add_comdat_section(const std::string& name, unsigned int shndx,
+                    uint64_t size)
+  {
+    gold_assert(this->is_comdat_);
+    Comdat_section_info sinfo(shndx, size);
+    this->u_.group_sections->insert(std::make_pair(name, sinfo));
+  }
+
+  // Look for a section name in the group list, and return whether it
+  // was found.  If found, returns the section index and size.
+  bool
+  find_comdat_section(const std::string& name, unsigned int *pshndx,
+                     uint64_t *psize) const
+  {
+    gold_assert(this->is_comdat_);
+    Comdat_group::const_iterator p = this->u_.group_sections->find(name);
+    if (p == this->u_.group_sections->end())
+      return false;
+    *pshndx = p->second.shndx;
+    *psize = p->second.size;
+    return true;
+  }
+
+  // If there is only one section in the group list, return true, and
+  // return the section index and size.
+  bool
+  find_single_comdat_section(unsigned int *pshndx, uint64_t *psize) const
+  {
+    gold_assert(this->is_comdat_);
+    if (this->u_.group_sections->size() != 1)
+      return false;
+    Comdat_group::const_iterator p = this->u_.group_sections->begin();
+    *pshndx = p->second.shndx;
+    *psize = p->second.size;
+    return true;
+  }
+
+  // Return the size of a linkonce section.
+  uint64_t
+  linkonce_size() const
+  {
+    gold_assert(!this->is_comdat_);
+    return this->u_.linkonce_size;
+  }
+
+  // Set the size of a linkonce section.
+  void
+  set_linkonce_size(uint64_t size)
+  {
+    gold_assert(!this->is_comdat_);
+    this->u_.linkonce_size = size;
+  }
 
-  typedef Unordered_map<std::string, unsigned int> Comdat_group;
+ private:
+  // No assignment.
+  Kept_section& operator=(const Kept_section&);
 
-  // The object containing the comdat or .gnu.linkonce.
-  Relobj* object;
-  // Index to the group section for comdats and the section itself for
+  // The object containing the comdat group or .gnu.linkonce section.
+  Relobj* object_;
+  // Index of the group section for comdats and the section itself for
   // .gnu.linkonce.
-  unsigned int shndx;
+  unsigned int shndx_;
+  // True if this is for a comdat group rather than a .gnu.linkonce
+  // section.
+  bool is_comdat_;
   // The Kept_sections are values of a mapping, that maps names to
   // them.  This field is true if this struct is associated with the
   // name of a comdat or .gnu.linkonce, false if it is associated with
   // the name of a symbol obtained from the .gnu.linkonce.* name
   // through some heuristics.
-  bool is_group;
-  // For comdats, a map from names of the sections in the group to
-  // indexes in OBJECT_.  NULL for .gnu.linkonce.
-  Comdat_group* group_sections;
+  bool is_group_name_;
+  union
+  {
+    // If the is_comdat_ field is true, this holds a map from names of
+    // the sections in the group to section indexes in object_ and to
+    // section sizes.
+    Comdat_group* group_sections;
+    // If the is_comdat_ field is false, this holds the size of the
+    // single section.
+    uint64_t linkonce_size;
+  } u_;
 };
 
 // This class handles the details of laying out input sections.
@@ -125,7 +286,13 @@ struct Kept_section
 class Layout
 {
  public:
-  Layout(const General_options& options, Script_options*);
+  Layout(int number_of_input_files, Script_options*);
+
+  ~Layout()
+  {
+    delete this->relaxation_debug_check_;
+    delete this->segment_states_;
+  }
 
   // Given an input section SHNDX, named NAME, with data in SHDR, from
   // the object file OBJECT, return the output section where this
@@ -193,11 +360,23 @@ class Layout
   layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
 
   // Add an Output_section_data to the layout.  This is used for
-  // special sections like the GOT section.
+  // special sections like the GOT section.  IS_DYNAMIC_LINKER_SECTION
+  // is true for sections which are used by the dynamic linker, such
+  // as dynamic reloc sections.  IS_RELRO is true for relro sections.
+  // IS_LAST_RELRO is true for the last relro section.
+  // IS_FIRST_NON_RELRO is true for the first section after the relro
+  // sections.
   Output_section*
   add_output_section_data(const char* name, elfcpp::Elf_Word type,
                          elfcpp::Elf_Xword flags,
-                         Output_section_data*);
+                         Output_section_data*, bool is_dynamic_linker_section,
+                         bool is_relro, bool is_last_relro,
+                         bool is_first_non_relro);
+
+  // Increase the size of the relro segment by this much.
+  void
+  increase_relro(unsigned int s)
+  { this->increase_relro_ += s; }
 
   // Create dynamic sections if necessary.
   void
@@ -207,6 +386,10 @@ class Layout
   void
   define_section_symbols(Symbol_table*);
 
+  // Create automatic note sections.
+  void
+  create_notes();
+
   // Create sections for linker scripts.
   void
   create_script_sections()
@@ -250,6 +433,11 @@ class Layout
   is_linkonce(const char* name)
   { return strncmp(name, ".gnu.linkonce", sizeof(".gnu.linkonce") - 1) == 0; }
 
+  // Whether we have added an input section.
+  bool
+  have_added_input_section() const
+  { return this->have_added_input_section_; }
+
   // Return true if a section is a debugging section.
   static inline bool
   is_debug_info_section(const char* name)
@@ -265,20 +453,14 @@ class Layout
   // Check if a comdat group or .gnu.linkonce section with the given
   // NAME is selected for the link.  If there is already a section,
   // *KEPT_SECTION is set to point to the signature and the function
-  // returns false.  Otherwise, the CANDIDATE signature is recorded
-  // for this NAME in the layout object, *KEPT_SECTION is set to the
-  // internal copy and the function return false.  In some cases, with
-  // CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
-  // CANDIDATE.
+  // returns false.  Otherwise, OBJECT, SHNDX,IS_COMDAT, and
+  // IS_GROUP_NAME are recorded for this NAME in the layout object,
+  // *KEPT_SECTION is set to the internal copy and the function return
+  // false.
   bool
-  find_or_add_kept_section(const std::string name,
-                           Kept_section* candidate,
-                           Kept_section** kept_section);
-
-  // Find the given comdat signature, and return the object and section
-  // index of the kept group.
-  Relobj*
-  find_kept_object(const std::string&, unsigned int*) const;
+  find_or_add_kept_section(const std::string& name, Relobj* object, 
+                          unsigned int shndx, bool is_comdat,
+                          bool is_group_name, Kept_section** kept_section);
 
   // Finalize the layout after all the input sections have been added.
   off_t
@@ -368,6 +550,12 @@ class Layout
   script_options() const
   { return this->script_options_; }
 
+  // Return the object managing inputs in incremental build. NULL in
+  // non-incremental builds.
+  Incremental_inputs*
+  incremental_inputs()
+  { return this->incremental_inputs_; }
+
   // Compute and write out the build ID if needed.
   void
   write_build_id(Output_file*) const;
@@ -422,20 +610,34 @@ class Layout
   void
   attach_sections_to_segments();
 
+  // For relaxation clean up, we need to know output section data created
+  // from a linker script.
+  void
+  new_output_section_data_from_script(Output_section_data* posd)
+  {
+    if (this->record_output_section_data_from_script_)
+      this->script_output_section_data_list_.push_back(posd);
+  }
+
+  // Return section list.
+  const Section_list&
+  section_list() const
+  { return this->section_list_; }
+
  private:
   Layout(const Layout&);
   Layout& operator=(const Layout&);
 
-  // Mapping from .gnu.linkonce section names to output section names.
-  struct Linkonce_mapping
+  // Mapping from input section names to output section names.
+  struct Section_name_mapping
   {
     const char* from;
     int fromlen;
     const char* to;
     int tolen;
   };
-  static const Linkonce_mapping linkonce_mapping[];
-  static const int linkonce_mapping_count;
+  static const Section_name_mapping section_name_mapping[];
+  static const int section_name_mapping_count;
 
   // During a relocatable link, a list of group sections and
   // signatures.
@@ -467,12 +669,21 @@ class Layout
 
   // Record whether the stack must be executable.
   void
-  create_executable_stack_info(const Target*);
+  create_executable_stack_info();
 
   // Create a build ID note if needed.
   void
   create_build_id();
 
+  // Link .stab and .stabstr sections.
+  void
+  link_stabs_sections();
+
+  // Create .gnu_incremental_inputs and .gnu_incremental_strtab sections needed
+  // for the next run of incremental linking to check what has changed.
+  void
+  create_incremental_info_sections();
+
   // Find the first read-only PT_LOAD segment, creating one if
   // necessary.
   Output_segment*
@@ -512,6 +723,10 @@ class Layout
   void
   finish_dynamic_section(const Input_objects*, const Symbol_table*);
 
+  // Set the size of the _DYNAMIC symbol.
+  void
+  set_dynamic_symbol_size(const Symbol_table*);
+
   // Create the .interp section and PT_INTERP segment.
   void
   create_interp(const Target* target);
@@ -544,11 +759,6 @@ class Layout
   static const char*
   output_section_name(const char* name, size_t* plen);
 
-  // Return the output section name to use for a linkonce section
-  // name.  PLEN is as for output_section_name.
-  static const char*
-  linkonce_output_name(const char* name, size_t* plen);
-
   // Return the number of allocated output sections.
   size_t
   allocated_output_section_count() const;
@@ -556,18 +766,25 @@ class Layout
   // Return the output section for NAME, TYPE and FLAGS.
   Output_section*
   get_output_section(const char* name, Stringpool::Key name_key,
-                    elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
+                    elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+                    bool is_interp, bool is_dynamic_linker_section,
+                    bool is_relro, bool is_last_relro,
+                    bool is_first_non_relro);
 
   // Choose the output section for NAME in RELOBJ.
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
                        elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-                       bool is_input_section);
+                       bool is_input_section, bool is_interp,
+                       bool is_dynamic_linker_section, bool is_relro,
+                       bool is_last_relro, bool is_first_non_relro);
 
   // Create a new Output_section.
   Output_section*
   make_output_section(const char* name, elfcpp::Elf_Word type,
-                     elfcpp::Elf_Xword flags);
+                     elfcpp::Elf_Xword flags, bool is_interp,
+                     bool is_dynamic_linker_section, bool is_relro,
+                     bool is_last_relro, bool is_first_non_relro);
 
   // Attach a section to a segment.
   void
@@ -610,10 +827,42 @@ class Layout
   Output_segment*
   set_section_addresses_from_script(Symbol_table*);
 
+  // Find appropriate places or orphan sections in a script.
+  void
+  place_orphan_sections_in_script();
+
   // Return whether SEG1 comes before SEG2 in the output file.
   static bool
   segment_precedes(const Output_segment* seg1, const Output_segment* seg2);
 
+  // Use to save and restore segments during relaxation. 
+  typedef Unordered_map<const Output_segment*, const Output_segment*>
+    Segment_states;
+
+  // Save states of current output segments.
+  void
+  save_segments(Segment_states*);
+
+  // Restore output segment states.
+  void
+  restore_segments(const Segment_states*);
+
+  // Clean up after relaxation so that it is possible to lay out the
+  // sections and segments again.
+  void
+  clean_up_after_relaxation();
+
+  // Doing preparation work for relaxation.  This is factored out to make
+  // Layout::finalized a bit smaller and easier to read.
+  void
+  prepare_for_relaxation();
+
+  // Main body of the relaxation loop, which lays out the section.
+  off_t
+  relaxation_loop_body(int, Target*, Symbol_table*, Output_segment**,
+                      Output_segment*, Output_segment_headers*,
+                      Output_file_header*, unsigned int*);
+
   // A mapping used for kept comdats/.gnu.linkonce group signatures.
   typedef Unordered_map<std::string, Kept_section> Signatures;
 
@@ -640,8 +889,49 @@ class Layout
     { return Layout::segment_precedes(seg1, seg2); }
   };
 
-  // A reference to the options on the command line.
-  const General_options& options_;
+  typedef std::vector<Output_section_data*> Output_section_data_list;
+
+  // Debug checker class.
+  class Relaxation_debug_check
+  {
+   public:
+    Relaxation_debug_check()
+      : section_infos_()
+    { }
+    // Check that sections and special data are in reset states.
+    void
+    check_output_data_for_reset_values(const Layout::Section_list&,
+                                      const Layout::Data_list&);
+  
+    // Record information of a section list.
+    void
+    read_sections(const Layout::Section_list&);
+
+    // Verify a section list with recorded information.
+    void
+    verify_sections(const Layout::Section_list&);
+   private:
+    // Information we care about a section.
+    struct Section_info
+    {
+      // Output section described by this.
+      Output_section* output_section;
+      // Load address.
+      uint64_t address;
+      // Data size.
+      off_t data_size;
+      // File offset.
+      off_t offset;
+    };
+
+    // Section information.
+    std::vector<Section_info> section_infos_;
+  };
+
+  // The number of input files, for sizing tables.
+  int number_of_input_files_;
   // Information set by scripts or by command line options.
   Script_options* script_options_;
   // The output section names.
@@ -661,8 +951,6 @@ class Layout
   // The list of output sections which are not attached to any output
   // segment.
   Section_list unattached_section_list_;
-  // Whether we have attached the sections to the segments.
-  bool sections_are_attached_;
   // The list of unattached Output_data objects which require special
   // handling because they are not Output_sections.
   Data_list special_output_list_;
@@ -672,6 +960,9 @@ class Layout
   Output_segment* tls_segment_;
   // A pointer to the PT_GNU_RELRO segment if there is one.
   Output_segment* relro_segment_;
+  // A backend may increase the size of the PT_GNU_RELRO segment if
+  // there is one.  This is the amount to increase it by.
+  unsigned int increase_relro_;
   // The SHT_SYMTAB output section.
   Output_section* symtab_section_;
   // The SHT_SYMTAB_SHNDX for the regular symbol table if there is one.
@@ -682,6 +973,8 @@ class Layout
   Output_symtab_xindex* dynsym_xindex_;
   // The SHT_DYNAMIC output section if there is one.
   Output_section* dynamic_section_;
+  // The _DYNAMIC symbol if there is one.
+  Symbol* dynamic_symbol_;
   // The dynamic data which goes into dynamic_section_.
   Output_data_dynamic* dynamic_data_;
   // The exception frame output section if there is one.
@@ -702,6 +995,10 @@ class Layout
   Group_signatures group_signatures_;
   // The size of the output file.
   off_t output_file_size_;
+  // Whether we have added an input section to an output section.
+  bool have_added_input_section_;
+  // Whether we have attached the sections to the segments.
+  bool sections_are_attached_;
   // Whether we have seen an object file marked to require an
   // executable stack.
   bool input_requires_executable_stack_;
@@ -715,6 +1012,21 @@ class Layout
   bool has_static_tls_;
   // Whether any sections require postprocessing.
   bool any_postprocessing_sections_;
+  // Whether we have resized the signatures_ hash table.
+  bool resized_signatures_;
+  // Whether we have created a .stab*str output section.
+  bool have_stabstr_section_;
+  // In incremental build, holds information check the inputs and build the
+  // .gnu_incremental_inputs section.
+  Incremental_inputs* incremental_inputs_;
+  // Whether we record output section data created in script
+  bool record_output_section_data_from_script_;
+  // List of output data that needs to be removed at relexation clean up.
+  Output_section_data_list script_output_section_data_list_;
+  // Structure to save segment states before entering the relaxation loop.
+  Segment_states* segment_states_;
+  // A relaxation debug checker.  We only create one when in debugging mode.
+  Relaxation_debug_check* relaxation_debug_check_;
 };
 
 // This task handles writing out data in output sections which is not