PR 10893
[binutils-gdb.git] / gold / object.h
index 02747a7caa6f277d78cd4b79c773afe749a9ce39..3412aec781b9762148ce60f256a9f139186bff3a 100644 (file)
@@ -39,6 +39,7 @@ class General_options;
 class Task;
 class Cref;
 class Layout;
+class Output_data;
 class Output_section;
 class Output_file;
 class Output_symtab_xindex;
@@ -387,6 +388,18 @@ class Object
   section_addralign(unsigned int shndx)
   { return this->do_section_addralign(shndx); }
 
+  // Return the output section given a section index.
+  Output_section*
+  output_section(unsigned int shndx) const
+  { return this->do_output_section(shndx); }
+
+  // Given a section index, return the offset in the Output_section.
+  // The return value will be -1U if the section is specially mapped,
+  // such as a merge section.
+  uint64_t
+  output_section_offset(unsigned int shndx) const
+  { return this->do_output_section_offset(shndx); }
+
   // Read the symbol information.
   void
   read_symbols(Read_symbols_data* sd)
@@ -405,9 +418,9 @@ class Object
 
   // Add symbol information to the global symbol table.
   Archive::Should_include
-  should_include_member(Symbol_table* symtab, Read_symbols_data* sd,
-                        std::string* why)
-  { return this->do_should_include_member(symtab, sd, why); }
+  should_include_member(Symbol_table* symtab, Layout* layout,
+                       Read_symbols_data* sd, std::string* why)
+  { return this->do_should_include_member(symtab, layout, sd, why); }
 
   // Functions and types for the elfcpp::Elf_file interface.  This
   // permit us to use Object as the File template parameter for
@@ -518,6 +531,23 @@ class Object
   set_no_export(bool value)
   { this->no_export_ = value; }
 
+  // Return TRUE if the section is a compressed debug section, and set
+  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
+  bool
+  section_is_compressed(unsigned int shndx,
+                       section_size_type* uncompressed_size) const
+  { return this->do_section_is_compressed(shndx, uncompressed_size); }
+
+  // Return the index of the first incremental relocation for symbol SYMNDX.
+  unsigned int
+  get_incremental_reloc_base(unsigned int symndx) const
+  { return this->do_get_incremental_reloc_base(symndx); }
+
+  // Return the number of incremental relocations for symbol SYMNDX.
+  unsigned int
+  get_incremental_reloc_count(unsigned int symndx) const
+  { return this->do_get_incremental_reloc_count(symndx); }
+
  protected:
   // Returns NULL for Objects that are not plugin objects.  This method
   // is overridden in the Pluginobj class.
@@ -539,7 +569,7 @@ class Object
   do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
 
   virtual Archive::Should_include
-  do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
                            std::string* why) = 0;
 
   // Return the location of the contents of a section.  Implemented by
@@ -583,6 +613,17 @@ class Object
   virtual uint64_t
   do_section_addralign(unsigned int shndx) = 0;
 
+  // Return the output section given a section index--implemented
+  // by child class.
+  virtual Output_section*
+  do_output_section(unsigned int) const
+  { gold_unreachable(); }
+
+  // Get the offset of a section--implemented by child class.
+  virtual uint64_t
+  do_output_section_offset(unsigned int) const
+  { gold_unreachable(); }
+
   // Return the Xindex structure to use.
   virtual Xindex*
   do_initialize_xindex() = 0;
@@ -628,6 +669,24 @@ class Object
   bool
   handle_split_stack_section(const char* name);
 
+  // Return TRUE if the section is a compressed debug section, and set
+  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
+  virtual bool
+  do_section_is_compressed(unsigned int, section_size_type*) const
+  { return false; }
+
+  // Return the index of the first incremental relocation for symbol SYMNDX--
+  // implemented by child class.
+  virtual unsigned int
+  do_get_incremental_reloc_base(unsigned int) const
+  { gold_unreachable(); }
+
+  // Return the number of incremental relocations for symbol SYMNDX--
+  // implemented by child class.
+  virtual unsigned int
+  do_get_incremental_reloc_count(unsigned int) const
+  { gold_unreachable(); }
+
  private:
   // This class may not be copied.
   Object(const Object&);
@@ -672,7 +731,9 @@ class Relobj : public Object
       map_to_relocatable_relocs_(NULL),
       object_merge_map_(NULL),
       relocs_must_follow_section_writes_(false),
-      sd_(NULL)
+      sd_(NULL),
+      reloc_counts_(NULL),
+      reloc_bases_(NULL)
   { }
 
   // During garbage collection, the Read_symbols_data pass for 
@@ -768,16 +829,6 @@ class Relobj : public Object
     return this->output_sections_[shndx] != NULL;
   }
 
-  // Given a section index, return the corresponding Output_section.
-  // The return value will be NULL if the section is not included in
-  // the link.
-  Output_section*
-  output_section(unsigned int shndx) const
-  {
-    gold_assert(shndx < this->output_sections_.size());
-    return this->output_sections_[shndx];
-  }
-
   // The the output section of the input section with index SHNDX.
   // This is only used currently to remove a section from the link in
   // relaxation.
@@ -788,13 +839,6 @@ class Relobj : public Object
     this->output_sections_[shndx] = os;
   }
   
-  // Given a section index, return the offset in the Output_section.
-  // The return value will be -1U if the section is specially mapped,
-  // such as a merge section.
-  uint64_t
-  output_section_offset(unsigned int shndx) const
-  { return this->do_output_section_offset(shndx); }
-
   // Set the offset of an input section within its output section.
   void
   set_section_offset(unsigned int shndx, uint64_t off)
@@ -843,6 +887,16 @@ class Relobj : public Object
   layout_deferred_sections(Layout* layout)
   { this->do_layout_deferred_sections(layout); }
 
+  // Return the index of the first incremental relocation for symbol SYMNDX.
+  virtual unsigned int
+  do_get_incremental_reloc_base(unsigned int symndx) const
+  { return this->reloc_bases_[symndx]; }
+
+  // Return the number of incremental relocations for symbol SYMNDX.
+  virtual unsigned int
+  do_get_incremental_reloc_count(unsigned int symndx) const
+  { return this->reloc_counts_[symndx]; }
+
  protected:
   // The output section to be used for each input section, indexed by
   // the input section number.  The output section is NULL if the
@@ -889,10 +943,6 @@ class Relobj : public Object
   virtual void
   do_relocate(const Symbol_table* symtab, const Layout*, Output_file* of) = 0;
 
-  // Get the offset of a section--implemented by child class.
-  virtual uint64_t
-  do_output_section_offset(unsigned int shndx) const = 0;
-
   // Set the offset of a section--implemented by child class.
   virtual void
   do_set_section_offset(unsigned int shndx, uint64_t off) = 0;
@@ -902,6 +952,16 @@ class Relobj : public Object
   virtual void
   do_layout_deferred_sections(Layout*) = 0;
 
+  // Given a section index, return the corresponding Output_section.
+  // The return value will be NULL if the section is not included in
+  // the link.
+  Output_section*
+  do_output_section(unsigned int shndx) const
+  {
+    gold_assert(shndx < this->output_sections_.size());
+    return this->output_sections_[shndx];
+  }
+
   // Return the vector mapping input sections to output sections.
   Output_sections&
   output_sections()
@@ -925,6 +985,46 @@ class Relobj : public Object
   set_relocs_must_follow_section_writes()
   { this->relocs_must_follow_section_writes_ = true; }
 
+  // Allocate the array for counting incremental relocations.
+  void
+  allocate_incremental_reloc_counts()
+  {
+    unsigned int nsyms = this->do_get_global_symbols()->size();
+    this->reloc_counts_ = new unsigned int[nsyms];
+    gold_assert(this->reloc_counts_ != NULL);
+    memset(this->reloc_counts_, 0, nsyms * sizeof(unsigned int));
+  }
+
+  // Record a relocation in this object referencing global symbol SYMNDX.
+  // Used for tracking incremental link information.
+  void
+  count_incremental_reloc(unsigned int symndx)
+  {
+    unsigned int nsyms = this->do_get_global_symbols()->size();
+    gold_assert(symndx < nsyms);
+    gold_assert(this->reloc_counts_ != NULL);
+    ++this->reloc_counts_[symndx];
+  }
+
+  // Finalize the incremental relocation information.
+  void
+  finalize_incremental_relocs(Layout* layout);
+
+  // Return the index of the next relocation to be written for global symbol
+  // SYMNDX.  Only valid after finalize_incremental_relocs() has been called.
+  unsigned int
+  next_incremental_reloc_index(unsigned int symndx)
+  {
+    unsigned int nsyms = this->do_get_global_symbols()->size();
+
+    gold_assert(this->reloc_counts_ != NULL);
+    gold_assert(this->reloc_bases_ != NULL);
+    gold_assert(symndx < nsyms);
+
+    unsigned int counter = this->reloc_counts_[symndx]++;
+    return this->reloc_bases_[symndx] + counter;
+  }
+
  private:
   // Mapping from input sections to output section.
   Output_sections output_sections_;
@@ -944,6 +1044,10 @@ class Relobj : public Object
   // Again used during garbage collection when laying out referenced
   // sections.
   gold::Symbols_data *sd_;
+  // Per-symbol counts of relocations, for incremental links.
+  unsigned int* reloc_counts_;
+  // Per-symbol base indexes of relocations, for incremental links.
+  unsigned int* reloc_bases_;
 };
 
 // This class is used to handle relocations against a section symbol
@@ -1048,7 +1152,7 @@ class Symbol_value
   Symbol_value()
     : output_symtab_index_(0), output_dynsym_index_(-1U), input_shndx_(0),
       is_ordinary_shndx_(false), is_section_symbol_(false),
-      is_tls_symbol_(false), has_output_value_(true)
+      is_tls_symbol_(false), is_ifunc_symbol_(false), has_output_value_(true)
   { this->u_.value = 0; }
 
   // Get the value of this symbol.  OBJECT is the object in which this
@@ -1261,11 +1365,21 @@ class Symbol_value
   set_is_tls_symbol()
   { this->is_tls_symbol_ = true; }
 
-  // Return TRUE if this is a TLS symbol.
+  // Return true if this is a TLS symbol.
   bool
   is_tls_symbol() const
   { return this->is_tls_symbol_; }
 
+  // Record that this is an IFUNC symbol.
+  void
+  set_is_ifunc_symbol()
+  { this->is_ifunc_symbol_ = true; }
+
+  // Return true if this is an IFUNC symbol.
+  bool
+  is_ifunc_symbol() const
+  { return this->is_ifunc_symbol_; }
+
  private:
   // The index of this local symbol in the output symbol table.  This
   // will be 0 if no value has been assigned yet, and the symbol may
@@ -1278,7 +1392,7 @@ class Symbol_value
   unsigned int output_dynsym_index_;
   // The section index in the input file in which this symbol is
   // defined.
-  unsigned int input_shndx_ : 28;
+  unsigned int input_shndx_ : 27;
   // Whether the section index is an ordinary index, not a special
   // value.
   bool is_ordinary_shndx_ : 1;
@@ -1286,6 +1400,8 @@ class Symbol_value
   bool is_section_symbol_ : 1;
   // Whether this is a STT_TLS symbol.
   bool is_tls_symbol_ : 1;
+  // Whether this is a STT_GNU_IFUNC symbol.
+  bool is_ifunc_symbol_ : 1;
   // Whether this symbol has a value for the output file.  This is
   // normally set to true during Layout::finalize, by
   // finalize_local_symbols.  It will be false for a section symbol in
@@ -1376,6 +1492,26 @@ class Got_offset_list
     return -1U;
   }
 
+  // Return a pointer to the list, or NULL if the list is empty.
+  const Got_offset_list*
+  get_list() const
+  {
+    if (this->got_type_ == -1U)
+      return NULL;
+    return this;
+  }
+
+  // Loop over all GOT offset entries, applying the function F to each.
+  template<typename F>
+  void
+  for_all_got_offsets(F f) const
+  {
+    if (this->got_type_ == -1U)
+      return;
+    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+      f(g->got_type_, g->got_offset_);
+  }
+
  private:
   unsigned int got_type_;
   unsigned int got_offset_;
@@ -1406,6 +1542,10 @@ class Reloc_symbol_changes
   std::vector<Symbol*> vec_;
 };
 
+// Type for mapping section index to uncompressed size.
+
+typedef std::map<unsigned int, section_size_type> Compressed_section_map;
+
 // A regular object file.  This is size and endian specific.
 
 template<int size, bool big_endian>
@@ -1554,6 +1694,30 @@ class Sized_relobj : public Relobj
       }
   }
 
+  // Return the GOT offset list for the local symbol SYMNDX.
+  const Got_offset_list*
+  local_got_offset_list(unsigned int symndx) const
+  {
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    if (p == this->local_got_offsets_.end())
+      return NULL;
+    return p->second;
+  }
+
+  // Return whether the local symbol SYMNDX has a PLT offset.
+  bool
+  local_has_plt_offset(unsigned int symndx) const;
+
+  // Return the PLT offset for a local symbol.  It is an error to call
+  // this if it doesn't have one.
+  unsigned int
+  local_plt_offset(unsigned int symndx) const;
+
+  // Set the PLT offset of the local symbol SYMNDX.
+  void
+  set_local_plt_offset(unsigned int symndx, unsigned int plt_offset);
+
   // Get the offset of input section SHNDX within its output section.
   // This is -1 if the input section requires a special mapping, such
   // as a merge section.  The output section can be found in the
@@ -1606,7 +1770,7 @@ class Sized_relobj : public Relobj
   do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
 
   Archive::Should_include
-  do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
+  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
                            std::string* why);
 
   // Read the relocs.
@@ -1775,13 +1939,33 @@ class Sized_relobj : public Relobj
   // This may be overriden by a child class.
   virtual void
   do_relocate_sections(const Symbol_table* symtab, const Layout* layout,
-                      const unsigned char* pshdrs, Views* pviews);
+                      const unsigned char* pshdrs, Output_file* of,
+                      Views* pviews);
 
   // Allow a child to set output local symbol count.
   void
   set_output_local_symbol_count(unsigned int value)
   { this->output_local_symbol_count_ = value; }
-   
+
+  // Return TRUE if the section is a compressed debug section, and set
+  // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
+  bool
+  do_section_is_compressed(unsigned int shndx,
+                          section_size_type* uncompressed_size) const
+  {
+    if (this->compressed_sections_ == NULL)
+      return false;
+    Compressed_section_map::const_iterator p =
+        this->compressed_sections_->find(shndx);
+    if (p != this->compressed_sections_->end())
+      {
+       if (uncompressed_size != NULL)
+         *uncompressed_size = p->second;
+       return true;
+      }
+    return false;
+  }
+
  private:
   // For convenience.
   typedef Sized_relobj<size, big_endian> This;
@@ -1844,8 +2028,9 @@ class Sized_relobj : public Relobj
   // Relocate the sections in the output file.
   void
   relocate_sections(const Symbol_table* symtab, const Layout* layout,
-                   const unsigned char* pshdrs, Views* pviews)
-  { this->do_relocate_sections(symtab, layout, pshdrs, pviews); }
+                   const unsigned char* pshdrs, Output_file* of,
+                   Views* pviews)
+  { this->do_relocate_sections(symtab, layout, pshdrs, of, pviews); }
 
   // Scan the input relocations for --emit-relocs.
   void
@@ -1882,6 +2067,35 @@ class Sized_relobj : public Relobj
                      unsigned char* reloc_view,
                      section_size_type reloc_view_size);
 
+  // Scan the input relocations for --incremental.
+  void
+  incremental_relocs_scan(const Read_relocs_data::Relocs_list::iterator&);
+
+  // Scan the input relocations for --incremental, templatized on the
+  // type of the relocation section.
+  template<int sh_type>
+  void
+  incremental_relocs_scan_reltype(
+      const Read_relocs_data::Relocs_list::iterator&);
+
+  void
+  incremental_relocs_write(const Relocate_info<size, big_endian>*,
+                          unsigned int sh_type,
+                          const unsigned char* prelocs,
+                          size_t reloc_count,
+                          Output_section*,
+                          Address output_offset,
+                          Output_file*);
+
+  template<int sh_type>
+  void
+  incremental_relocs_write_reltype(const Relocate_info<size, big_endian>*,
+                                  const unsigned char* prelocs,
+                                  size_t reloc_count,
+                                  Output_section*,
+                                  Address output_offset,
+                                  Output_file*);
+
   // A type shared by split_stack_adjust_reltype and find_functions.
   typedef std::map<section_offset_type, section_size_type> Function_offsets;
 
@@ -1920,6 +2134,7 @@ class Sized_relobj : public Relobj
   {
     this->local_values_.clear();
     this->local_got_offsets_.clear();
+    this->local_plt_offsets_.clear();
   }
 
   // Record a mapping from discarded section SHNDX to the corresponding
@@ -1951,20 +2166,8 @@ class Sized_relobj : public Relobj
   // for tp-relative offsets for TLS symbols.
   typedef Unordered_map<unsigned int, Got_offset_list*> Local_got_offsets;
 
-  // The TLS GOT offsets of local symbols. The map stores the offsets
-  // for either a single GOT entry that holds the module index of a TLS
-  // symbol, or a pair of GOT entries containing the module index and
-  // dtv-relative offset.
-  struct Tls_got_entry
-  {
-    Tls_got_entry(int got_offset, bool have_pair)
-      : got_offset_(got_offset),
-        have_pair_(have_pair)
-    { }
-    int got_offset_;
-    bool have_pair_;
-  };
-  typedef Unordered_map<unsigned int, Tls_got_entry> Local_tls_got_offsets;
+  // The PLT offsets of local symbols.
+  typedef Unordered_map<unsigned int, unsigned int> Local_plt_offsets;
 
   // Saved information for sections whose layout was deferred.
   struct Deferred_layout
@@ -2009,6 +2212,8 @@ class Sized_relobj : public Relobj
   // GOT offsets for local non-TLS symbols, and tp-relative offsets
   // for TLS symbols, indexed by symbol number.
   Local_got_offsets local_got_offsets_;
+  // PLT offsets for local symbols.
+  Local_plt_offsets local_plt_offsets_;
   // For each input section, the offset of the input section in its
   // output section.  This is INVALID_ADDRESS if the input section requires a
   // special mapping.
@@ -2022,6 +2227,10 @@ class Sized_relobj : public Relobj
   unsigned int discarded_eh_frame_shndx_;
   // The list of sections whose layout was deferred.
   std::vector<Deferred_layout> deferred_layout_;
+  // The list of relocation sections whose layout was deferred.
+  std::vector<Deferred_layout> deferred_layout_relocs_;
+  // For compressed debug sections, map section index to uncompressed size.
+  Compressed_section_map* compressed_sections_;
 };
 
 // A class to manage the list of all objects.