* archive.cc (Archive::include_member): Adjust call to
[deliverable/binutils-gdb.git] / gold / object.h
index 187a10179b558c41a925af22d6be127228b0e4db..c814e76494a06fc150f085775f8dfc8b47fb8dca 100644 (file)
@@ -1,6 +1,6 @@
 // object.h -- support for an object file for linking in gold  -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -30,6 +30,7 @@
 #include "elfcpp_file.h"
 #include "fileread.h"
 #include "target.h"
+#include "archive.h"
 
 namespace gold
 {
@@ -37,8 +38,8 @@ namespace gold
 class General_options;
 class Task;
 class Cref;
-class Archive;
 class Layout;
+class Output_data;
 class Output_section;
 class Output_file;
 class Output_symtab_xindex;
@@ -55,6 +56,13 @@ class Stringpool_template;
 
 struct Read_symbols_data
 {
+  Read_symbols_data()
+    : section_headers(NULL), section_names(NULL), symbols(NULL),
+      symbol_names(NULL), versym(NULL), verdef(NULL), verneed(NULL)
+  { }
+
+  ~Read_symbols_data();
+
   // Section headers.
   File_view* section_headers;
   // Section names.
@@ -102,6 +110,13 @@ struct Symbol_location_info
 
 struct Section_relocs
 {
+  Section_relocs()
+    : contents(NULL)
+  { }
+
+  ~Section_relocs()
+  { delete this->contents; }
+
   // Index of reloc section.
   unsigned int reloc_shndx;
   // Index of section that relocs apply to.
@@ -125,6 +140,13 @@ struct Section_relocs
 
 struct Read_relocs_data
 {
+  Read_relocs_data()
+    : local_symbols(NULL)
+  { }
+
+  ~Read_relocs_data()
+  { delete this->local_symbols; }
+
   typedef std::vector<Section_relocs> Relocs_list;
   // The relocations.
   Relocs_list relocs;
@@ -181,6 +203,117 @@ class Xindex
   Symtab_xindex symtab_xindex_;
 };
 
+// A GOT offset list.  A symbol may have more than one GOT offset
+// (e.g., when mixing modules compiled with two different TLS models),
+// but will usually have at most one.  GOT_TYPE identifies the type of
+// GOT entry; its values are specific to each target.
+
+class Got_offset_list
+{
+ public:
+  Got_offset_list()
+    : got_type_(-1U), got_offset_(0), got_next_(NULL)
+  { }
+
+  Got_offset_list(unsigned int got_type, unsigned int got_offset)
+    : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
+  { }
+
+  ~Got_offset_list()
+  {
+    if (this->got_next_ != NULL)
+      {
+        delete this->got_next_;
+        this->got_next_ = NULL;
+      }
+  }
+
+  // Initialize the fields to their default values.
+  void
+  init()
+  {
+    this->got_type_ = -1U;
+    this->got_offset_ = 0;
+    this->got_next_ = NULL;
+  }
+
+  // Set the offset for the GOT entry of type GOT_TYPE.
+  void
+  set_offset(unsigned int got_type, unsigned int got_offset)
+  {
+    if (this->got_type_ == -1U)
+      {
+        this->got_type_ = got_type;
+        this->got_offset_ = got_offset;
+      }
+    else
+      {
+        for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
+          {
+            if (g->got_type_ == got_type)
+              {
+                g->got_offset_ = got_offset;
+                return;
+              }
+          }
+        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+        g->got_next_ = this->got_next_;
+        this->got_next_ = g;
+      }
+  }
+
+  // Return the offset for a GOT entry of type GOT_TYPE.
+  unsigned int
+  get_offset(unsigned int got_type) const
+  {
+    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+      {
+        if (g->got_type_ == got_type)
+          return g->got_offset_;
+      }
+    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;
+  }
+
+  // Abstract visitor class for iterating over GOT offsets.
+  class Visitor
+  {
+   public:
+    Visitor()
+    { }
+
+    virtual
+    ~Visitor()
+    { }
+
+    virtual void
+    visit(unsigned int, unsigned int) = 0;
+  };
+
+  // Loop over all GOT offset entries, calling a visitor class V for each.
+  void
+  for_all_got_offsets(Visitor* v) const
+  {
+    if (this->got_type_ == -1U)
+      return;
+    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
+      v->visit(g->got_type_, g->got_offset_);
+  }
+
+ private:
+  unsigned int got_type_;
+  unsigned int got_offset_;
+  Got_offset_list* got_next_;
+};
+
 // Object is an abstract base class which represents either a 32-bit
 // or a 64-bit input object.  This can be a regular object file
 // (ET_REL) or a shared object (ET_DYN).
@@ -188,6 +321,8 @@ class Xindex
 class Object
 {
  public:
+  typedef std::vector<Symbol*> Symbols;
+
   // NAME is the name of the object as we would report it to the user
   // (e.g., libfoo.a(bar.o) if this is in an archive.  INPUT_FILE is
   // used to read the file.  OFFSET is the offset within the input
@@ -196,11 +331,21 @@ class Object
         off_t offset = 0)
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
       is_dynamic_(is_dynamic), is_needed_(false), uses_split_stack_(false),
-      has_no_split_stack_(false), no_export_(false), xindex_(NULL)
-  { input_file->file().add_object(); }
+      has_no_split_stack_(false), no_export_(false),
+      is_in_system_directory_(false), xindex_(NULL)
+  {
+    if (input_file != NULL)
+      {
+       input_file->file().add_object();
+       this->is_in_system_directory_ = input_file->is_in_system_directory();
+      }
+  }
 
   virtual ~Object()
-  { this->input_file_->file().remove_object(); }
+  {
+    if (this->input_file_ != NULL)
+      this->input_file_->file().remove_object();
+  }
 
   // Return the name of the object as we would report it to the tuser.
   const std::string&
@@ -250,42 +395,71 @@ class Object
   // Get the file.  We pass on const-ness.
   Input_file*
   input_file()
-  { return this->input_file_; }
+  {
+    gold_assert(this->input_file_ != NULL);
+    return this->input_file_;
+  }
 
   const Input_file*
   input_file() const
-  { return this->input_file_; }
+  {
+    gold_assert(this->input_file_ != NULL);
+    return this->input_file_;
+  }
 
   // Lock the underlying file.
   void
   lock(const Task* t)
-  { this->input_file()->file().lock(t); }
+  {
+    if (this->input_file_ != NULL)
+      this->input_file_->file().lock(t);
+  }
 
   // Unlock the underlying file.
   void
   unlock(const Task* t)
-  { this->input_file()->file().unlock(t); }
+  {
+    if (this->input_file_ != NULL)
+      this->input_file()->file().unlock(t);
+  }
 
   // Return whether the underlying file is locked.
   bool
   is_locked() const
-  { return this->input_file()->file().is_locked(); }
+  { return this->input_file_ != NULL && this->input_file_->file().is_locked(); }
 
   // Return the token, so that the task can be queued.
   Task_token*
   token()
-  { return this->input_file()->file().token(); }
+  {
+    if (this->input_file_ == NULL)
+      return NULL;
+    return this->input_file()->file().token();
+  }
 
   // Release the underlying file.
   void
   release()
-  { this->input_file_->file().release(); }
+  {
+    if (this->input_file_ != NULL)
+      this->input_file()->file().release();
+  }
 
   // Return whether we should just read symbols from this file.
   bool
   just_symbols() const
   { return this->input_file()->just_symbols(); }
 
+  // Return whether this is an incremental object.
+  bool
+  is_incremental() const
+  { return this->do_is_incremental(); }
+
+  // Return the last modified time of the file.
+  Timespec
+  get_mtime()
+  { return this->do_get_mtime(); }
+
   // Get the number of sections.
   unsigned int
   shnum() const
@@ -364,6 +538,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)
@@ -380,6 +566,24 @@ class Object
   add_symbols(Symbol_table* symtab, Read_symbols_data* sd, Layout *layout)
   { this->do_add_symbols(symtab, sd, layout); }
 
+  // Add symbol information to the global symbol table.
+  Archive::Should_include
+  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); }
+
+  // Iterate over global symbols, calling a visitor class V for each.
+  void
+  for_all_global_symbols(Read_symbols_data* sd,
+                        Library_base::Symbol_visitor_base* v)
+  { return this->do_for_all_global_symbols(sd, v); }
+
+  // Iterate over local symbols, calling a visitor class V for each GOT offset
+  // associated with a local symbol.
+  void
+  for_all_local_got_entries(Got_offset_list::Visitor* v) const
+  { this->do_for_all_local_got_entries(v); }
+
   // Functions and types for the elfcpp::Elf_file interface.  This
   // permit us to use Object as the File template parameter for
   // elfcpp::Elf_file.
@@ -456,7 +660,10 @@ class Object
   // Stop caching views in the underlying file.
   void
   clear_view_cache_marks()
-  { this->input_file()->file().clear_view_cache_marks(); }
+  {
+    if (this->input_file_ != NULL)
+      this->input_file_->file().clear_view_cache_marks();
+  }
 
   // Get the number of global symbols defined by this object, and the
   // number of the symbols whose final definition came from this
@@ -466,10 +673,20 @@ class Object
                           size_t* used) const
   { this->do_get_global_symbol_counts(symtab, defined, used); }
 
+  // Get the symbols defined in this object.
+  const Symbols*
+  get_global_symbols() const
+  { return this->do_get_global_symbols(); }
+
+  // Set flag that this object was found in a system directory.
+  void
+  set_is_in_system_directory()
+  { this->is_in_system_directory_ = true; }
+
   // Return whether this object was found in a system directory.
   bool
   is_in_system_directory() const
-  { return this->input_file()->is_in_system_directory(); }
+  { return this->is_in_system_directory_; }
 
   // Return whether we found this object by searching a directory.
   bool
@@ -484,6 +701,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.
@@ -491,6 +725,20 @@ class Object
   do_pluginobj()
   { return NULL; }
 
+  // Return TRUE if this is an incremental (unchanged) input file.
+  // We return FALSE by default; the incremental object classes
+  // override this method.
+  virtual bool
+  do_is_incremental() const
+  { return false; }
+
+  // Return the last modified time of the file.  This method may be
+  // overridden for subclasses that don't use an actual file (e.g.,
+  // Incremental objects).
+  virtual Timespec
+  do_get_mtime()
+  { return this->input_file()->file().get_mtime(); }
+
   // Read the symbols--implemented by child class.
   virtual void
   do_read_symbols(Read_symbols_data*) = 0;
@@ -504,6 +752,20 @@ class Object
   virtual void
   do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
 
+  virtual Archive::Should_include
+  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
+                           std::string* why) = 0;
+
+  // Iterate over global symbols, calling a visitor class V for each.
+  virtual void
+  do_for_all_global_symbols(Read_symbols_data* sd,
+                           Library_base::Symbol_visitor_base* v) = 0;
+
+  // Iterate over local symbols, calling a visitor class V for each GOT offset
+  // associated with a local symbol.
+  virtual void
+  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const = 0;
+
   // Return the location of the contents of a section.  Implemented by
   // child class.
   virtual Location
@@ -545,6 +807,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;
@@ -553,6 +826,9 @@ class Object
   virtual void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const = 0;
 
+  virtual const Symbols*
+  do_get_global_symbols() const = 0;
+
   // Set the number of sections.
   void
   set_shnum(int shnum)
@@ -582,11 +858,29 @@ class Object
                             Symbol_table*);
 
   // If NAME is the name of the special section which indicates that
-  // this object was compiled with -fstack-split, mark it accordingly,
+  // this object was compiled with -fsplit-stack, mark it accordingly,
   // and return true.  Otherwise return false.
   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&);
@@ -615,6 +909,8 @@ class Object
   // True if exclude this object from automatic symbol export.
   // This is used only for archive objects.
   bool no_export_ : 1;
+  // True if the object was found in a system directory.
+  bool is_in_system_directory_ : 1;
   // Many sections for objects with more than SHN_LORESERVE sections.
   Xindex* xindex_;
 };
@@ -631,7 +927,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 
@@ -644,7 +942,7 @@ class Relobj : public Object
   // Decides which section names have to be included in the worklist
   // as roots.
   bool
-  is_section_name_included(const char *name);
+  is_section_name_included(const charname);
  
   void
   copy_symbols_data(Symbols_data* gc_sd, Read_symbols_data* sd,
@@ -727,23 +1025,16 @@ 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
+  // 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.
+  void
+  set_output_section(unsigned int shndx, Output_section* os)
   {
     gold_assert(shndx < this->output_sections_.size());
-    return this->output_sections_[shndx];
+    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)
@@ -792,6 +1083,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
@@ -838,10 +1139,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;
@@ -851,6 +1148,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()
@@ -874,6 +1181,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, bool clear_counts);
+
+  // 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_;
@@ -892,7 +1239,11 @@ class Relobj : public Object
   // Used to store the symbols data computed by the Read_symbols pass.
   // Again used during garbage collection when laying out referenced
   // sections.
-  gold::Symbols_data *sd_;
+  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
@@ -997,9 +1348,15 @@ 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; }
 
+  ~Symbol_value()
+  {
+    if (!this->has_output_value_)
+      delete this->u_.merged_symbol_value;
+  }
+
   // Get the value of this symbol.  OBJECT is the object in which this
   // symbol is defined, and ADDEND is an addend to add to the value.
   template<bool big_endian>
@@ -1067,17 +1424,39 @@ class Symbol_value
   input_value() const
   { return this->u_.value; }
 
-  // Return whether this symbol should go into the output symbol
+  // Return whether we have set the index in the output symbol table
+  // yet.
+  bool
+  is_output_symtab_index_set() const
+  {
+    return (this->output_symtab_index_ != 0
+           && this->output_symtab_index_ != -2U);
+  }
+
+  // Return whether this symbol may be discarded from the normal
+  // symbol table.
+  bool
+  may_be_discarded_from_output_symtab() const
+  {
+    gold_assert(!this->is_output_symtab_index_set());
+    return this->output_symtab_index_ != -2U;
+  }
+
+  // Return whether this symbol has an entry in the output symbol
   // table.
   bool
-  needs_output_symtab_entry() const
-  { return this->output_symtab_index_ != -1U; }
+  has_output_symtab_entry() const
+  {
+    gold_assert(this->is_output_symtab_index_set());
+    return this->output_symtab_index_ != -1U;
+  }
 
   // Return the index in the output symbol table.
   unsigned int
   output_symtab_index() const
   {
-    gold_assert(this->output_symtab_index_ != 0);
+    gold_assert(this->is_output_symtab_index_set()
+               && this->output_symtab_index_ != -1U);
     return this->output_symtab_index_;
   }
 
@@ -1085,7 +1464,8 @@ class Symbol_value
   void
   set_output_symtab_index(unsigned int i)
   {
-    gold_assert(this->output_symtab_index_ == 0);
+    gold_assert(!this->is_output_symtab_index_set());
+    gold_assert(i != 0 && i != -1U && i != -2U);
     this->output_symtab_index_ = i;
   }
 
@@ -1098,6 +1478,15 @@ class Symbol_value
     this->output_symtab_index_ = -1U;
   }
 
+  // Record that this symbol must go into the output symbol table,
+  // because it there is a relocation that uses it.
+  void
+  set_must_have_output_symtab_entry()
+  {
+    gold_assert(!this->is_output_symtab_index_set());
+    this->output_symtab_index_ = -2U;
+  }
+
   // Set the index in the output dynamic symbol table.
   void
   set_needs_output_dynsym_entry()
@@ -1106,7 +1495,7 @@ class Symbol_value
     this->output_dynsym_index_ = 0;
   }
 
-  // Return whether this symbol should go into the output symbol
+  // Return whether this symbol should go into the dynamic symbol
   // table.
   bool
   needs_output_dynsym_entry() const
@@ -1114,11 +1503,21 @@ class Symbol_value
     return this->output_dynsym_index_ != -1U;
   }
 
+  // Return whether this symbol has an entry in the dynamic symbol
+  // table.
+  bool
+  has_output_dynsym_entry() const
+  {
+    gold_assert(this->output_dynsym_index_ != 0);
+    return this->output_dynsym_index_ != -1U;
+  }
+
   // Record that this symbol should go into the dynamic symbol table.
   void
   set_output_dynsym_index(unsigned int i)
   {
     gold_assert(this->output_dynsym_index_ == 0);
+    gold_assert(i != 0 && i != -1U);
     this->output_dynsym_index_ = i;
   }
 
@@ -1168,21 +1567,39 @@ 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_; }
+
+  // Return true if this has output value.
+  bool
+  has_output_value() const
+  { return this->has_output_value_; }
+
  private:
   // The index of this local symbol in the output symbol table.  This
-  // will be -1 if the symbol should not go into the symbol table.
+  // will be 0 if no value has been assigned yet, and the symbol may
+  // be omitted.  This will be -1U if the symbol should not go into
+  // the symbol table.  This will be -2U if the symbol must go into
+  // the symbol table, but no index has been assigned yet.
   unsigned int output_symtab_index_;
   // The index of this local symbol in the dynamic symbol table.  This
-  // will be -1 if the symbol should not go into the symbol table.
+  // will be -1U if the symbol should not go into the symbol table.
   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;
@@ -1190,6 +1607,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
@@ -1209,83 +1628,6 @@ class Symbol_value
   } u_;
 };
 
-// A GOT offset list.  A symbol may have more than one GOT offset
-// (e.g., when mixing modules compiled with two different TLS models),
-// but will usually have at most one.  GOT_TYPE identifies the type of
-// GOT entry; its values are specific to each target.
-
-class Got_offset_list
-{
- public:
-  Got_offset_list()
-    : got_type_(-1U), got_offset_(0), got_next_(NULL)
-  { }
-
-  Got_offset_list(unsigned int got_type, unsigned int got_offset)
-    : got_type_(got_type), got_offset_(got_offset), got_next_(NULL)
-  { }
-
-  ~Got_offset_list()
-  { 
-    if (this->got_next_ != NULL)
-      {
-        delete this->got_next_;
-        this->got_next_ = NULL;
-      }
-  }
-
-  // Initialize the fields to their default values.
-  void
-  init()
-  {
-    this->got_type_ = -1U;
-    this->got_offset_ = 0;
-    this->got_next_ = NULL;
-  }
-
-  // Set the offset for the GOT entry of type GOT_TYPE.
-  void
-  set_offset(unsigned int got_type, unsigned int got_offset)
-  {
-    if (this->got_type_ == -1U)
-      {
-        this->got_type_ = got_type;
-        this->got_offset_ = got_offset;
-      }
-    else
-      {
-        for (Got_offset_list* g = this; g != NULL; g = g->got_next_)
-          {
-            if (g->got_type_ == got_type)
-              {
-                g->got_offset_ = got_offset;
-                return;
-              }
-          }
-        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
-        g->got_next_ = this->got_next_;
-        this->got_next_ = g;
-      }
-  }
-
-  // Return the offset for a GOT entry of type GOT_TYPE.
-  unsigned int
-  get_offset(unsigned int got_type) const
-  {
-    for (const Got_offset_list* g = this; g != NULL; g = g->got_next_)
-      {
-        if (g->got_type_ == got_type)
-          return g->got_offset_;
-      }
-    return -1U;
-  }
-
- private:
-  unsigned int got_type_;
-  unsigned int got_offset_;
-  Got_offset_list* got_next_;
-};
-
 // This type is used to modify relocations for -fsplit-stack.  It is
 // indexed by relocation index, and means that the relocation at that
 // index should use the symbol from the vector, rather than the one
@@ -1310,18 +1652,59 @@ 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;
+
+// Abstract base class for a regular object file, either a real object file
+// or an incremental (unchanged) object.  This is size and endian specific.
+
+template<int size, bool big_endian>
+class Sized_relobj_base : public Relobj
+{
+ public:
+  typedef Relobj::Symbols Symbols;
+
+  Sized_relobj_base(const std::string& name, Input_file* input_file)
+    : Relobj(name, input_file)
+  { }
+
+  Sized_relobj_base(const std::string& name, Input_file* input_file,
+                   off_t offset)
+    : Relobj(name, input_file, offset)
+  { }
+
+  ~Sized_relobj_base()
+  { }
+
+ protected:
+  typedef Relobj::Output_sections Output_sections;
+
+ private:
+};
+
 // A regular object file.  This is size and endian specific.
 
 template<int size, bool big_endian>
-class Sized_relobj : public Relobj
+class Sized_relobj : public Sized_relobj_base<size, big_endian>
 {
  public:
   typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
-  typedef std::vector<Symbol*> Symbols;
+  typedef typename Sized_relobj_base<size, big_endian>::Symbols Symbols;
   typedef std::vector<Symbol_value<size> > Local_values;
 
   static const Address invalid_address = static_cast<Address>(0) - 1;
 
+  enum Compute_final_local_value_status
+  {
+    // No error.
+    CFLV_OK,
+    // An error occurred.
+    CFLV_ERROR,
+    // The local symbol has no output section.
+    CFLV_DISCARDED
+  };
+
   Sized_relobj(const std::string& name, Input_file* input_file, off_t offset,
               const typename elfcpp::Ehdr<size, big_endian>&);
 
@@ -1401,6 +1784,14 @@ class Sized_relobj : public Relobj
     return this->local_values_[sym].input_shndx(is_ordinary);
   }
 
+  // Record that local symbol SYM must be in the output symbol table.
+  void
+  set_must_have_output_symtab_entry(unsigned int sym)
+  {
+    gold_assert(sym < this->local_values_.size());
+    this->local_values_[sym].set_must_have_output_symtab_entry();
+  }
+
   // Record that local symbol SYM needs a dynamic symbol entry.
   void
   set_needs_output_dynsym_entry(unsigned int sym)
@@ -1450,6 +1841,19 @@ class Sized_relobj : public Relobj
       }
   }
 
+  // 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
@@ -1474,12 +1878,26 @@ class Sized_relobj : public Relobj
   Address
   map_to_kept_section(unsigned int shndx, bool* found) const;
 
-  // Make section offset invalid.  This is needed for relaxation.
-  void
-  invalidate_section_offset(unsigned int shndx)
-  { this->do_invalidate_section_offset(shndx); }
+  // Compute final local symbol value.  R_SYM is the local symbol index.
+  // LV_IN points to a local symbol value containing the input value.
+  // LV_OUT points to a local symbol value storing the final output value,
+  // which must not be a merged symbol value since before calling this
+  // method to avoid memory leak.  SYMTAB points to a symbol table.
+  //
+  // The method returns a status code at return.  If the return status is
+  // CFLV_OK, *LV_OUT contains the final value.  If the return status is
+  // CFLV_ERROR, *LV_OUT is 0.  If the return status is CFLV_DISCARDED,
+  // *LV_OUT is not modified.
+  Compute_final_local_value_status
+  compute_final_local_value(unsigned int r_sym,
+                           const Symbol_value<size>* lv_in,
+                           Symbol_value<size>* lv_out,
+                           const Symbol_table* symtab);
 
  protected:
+  typedef typename Sized_relobj_base<size, big_endian>::Output_sections
+      Output_sections;
+
   // Set up.
   virtual void
   do_setup();
@@ -1506,6 +1924,20 @@ class Sized_relobj : public Relobj
   void
   do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
 
+  Archive::Should_include
+  do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
+                           std::string* why);
+
+  // Iterate over global symbols, calling a visitor class V for each.
+  void
+  do_for_all_global_symbols(Read_symbols_data* sd,
+                           Library_base::Symbol_visitor_base* v);
+
+  // Iterate over local symbols, calling a visitor class V for each GOT offset
+  // associated with a local symbol.
+  void
+  do_for_all_local_got_entries(Got_offset_list::Visitor* v) const;
+
   // Read the relocs.
   void
   do_read_relocs(Read_relocs_data*);
@@ -1596,6 +2028,11 @@ class Sized_relobj : public Relobj
   void
   do_get_global_symbol_counts(const Symbol_table*, size_t*, size_t*) const;
 
+  // Get the global symbols.
+  const Symbols*
+  do_get_global_symbols() const
+  { return &this->symbols_; }
+
   // Get the offset of a section.
   uint64_t
   do_output_section_offset(unsigned int shndx) const
@@ -1611,15 +2048,10 @@ class Sized_relobj : public Relobj
   do_set_section_offset(unsigned int shndx, uint64_t off)
   {
     gold_assert(shndx < this->section_offsets_.size());
-    this->section_offsets_[shndx] = convert_types<Address, uint64_t>(off);
-  }
-
-  // Set the offset of a section to invalid_address.
-  virtual void
-  do_invalidate_section_offset(unsigned int shndx)
-  {
-    gold_assert(shndx < this->section_offsets_.size());
-    this->section_offsets_[shndx] = invalid_address;
+    this->section_offsets_[shndx] =
+      (off == static_cast<uint64_t>(-1)
+       ? invalid_address
+       : convert_types<Address, uint64_t>(off));
   }
 
   // Adjust a section index if necessary.
@@ -1672,7 +2104,32 @@ 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.
@@ -1714,7 +2171,7 @@ class Sized_relobj : public Relobj
   // Whether to include a section group in the link.
   bool
   include_section_group(Symbol_table*, Layout*, unsigned int, const char*,
-                       const unsigned char*, const char *, section_size_type,
+                       const unsigned char*, const char*, section_size_type,
                        std::vector<bool>*);
 
   // Whether to include a linkonce section in the link.
@@ -1736,8 +2193,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
@@ -1774,6 +2232,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;
 
@@ -1804,15 +2291,8 @@ class Sized_relobj : public Relobj
                      const Stringpool_template<char>*,
                      const Stringpool_template<char>*,
                      Output_symtab_xindex*,
-                     Output_symtab_xindex*);
-
-  // Clear the local symbol information.
-  void
-  clear_local_symbols()
-  {
-    this->local_values_.clear();
-    this->local_got_offsets_.clear();
-  }
+                     Output_symtab_xindex*,
+                     off_t);
 
   // Record a mapping from discarded section SHNDX to the corresponding
   // kept section.
@@ -1839,24 +2319,34 @@ class Sized_relobj : public Relobj
     return true;
   }
 
+  // Compute final local symbol value.  R_SYM is the local symbol index.
+  // LV_IN points to a local symbol value containing the input value.
+  // LV_OUT points to a local symbol value storing the final output value,
+  // which must not be a merged symbol value since before calling this
+  // method to avoid memory leak.  RELOCATABLE indicates whether we are
+  // linking a relocatable output.  OUT_SECTIONS is an array of output
+  // sections.  OUT_OFFSETS is an array of offsets of the sections.  SYMTAB
+  // points to a symbol table.
+  //
+  // The method returns a status code at return.  If the return status is
+  // CFLV_OK, *LV_OUT contains the final value.  If the return status is
+  // CFLV_ERROR, *LV_OUT is 0.  If the return status is CFLV_DISCARDED,
+  // *LV_OUT is not modified.
+  inline Compute_final_local_value_status
+  compute_final_local_value_internal(unsigned int r_sym,
+                                    const Symbol_value<size>* lv_in,
+                                    Symbol_value<size>* lv_out,
+                                    bool relocatable,
+                                    const Output_sections& out_sections,
+                                    const std::vector<Address>& out_offsets,
+                                    const Symbol_table* symtab);
+
   // The GOT offsets of local symbols. This map also stores GOT offsets
   // 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
@@ -1892,15 +2382,17 @@ class Sized_relobj : public Relobj
   Symbols symbols_;
   // Number of symbols defined in object file itself.
   size_t defined_count_;
-  // File offset for local symbols.
+  // File offset for local symbols (relative to start of symbol table).
   off_t local_symbol_offset_;
-  // File offset for local dynamic symbols.
+  // File offset for local dynamic symbols (absolute).
   off_t local_dynsym_offset_;
   // Values of local symbols.
   Local_values local_values_;
   // 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.
@@ -1914,6 +2406,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.
@@ -1960,6 +2456,10 @@ class Input_objects
   void
   print_symbol_counts(const Symbol_table*) const;
 
+  // Print a cross reference table.
+  void
+  print_cref(const Symbol_table*, FILE*) const;
+
   // Iterate over all regular objects.
 
   Relobj_iterator
@@ -1985,6 +2485,11 @@ class Input_objects
   any_dynamic() const
   { return !this->dynobj_list_.empty(); }
 
+  // Return the number of non dynamic objects.
+  int
+  number_of_relobjs() const
+  { return this->relobj_list_.size(); }
+
   // Return the number of input objects.
   int
   number_of_input_objects() const
@@ -2031,13 +2536,38 @@ struct Relocate_info
   location(size_t relnum, off_t reloffset) const;
 };
 
+// This is used to represent a section in an object and is used as the
+// key type for various section maps.
+typedef std::pair<Object*, unsigned int> Section_id;
+
+// This is similar to Section_id but is used when the section
+// pointers are const.
+typedef std::pair<const Object*, unsigned int> Const_section_id;
+
+// The hash value is based on the address of an object in memory during
+// linking.  It is okay to use this for looking up sections but never use
+// this in an unordered container that we want to traverse in a repeatable
+// manner.
+
+struct Section_id_hash
+{
+  size_t operator()(const Section_id& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
+struct Const_section_id_hash
+{
+  size_t operator()(const Const_section_id& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.first) ^ loc.second; }
+};
+
 // Return whether INPUT_FILE contains an ELF object start at file
 // offset OFFSET.  This sets *START to point to a view of the start of
 // the file.  It sets *READ_SIZE to the number of bytes in the view.
 
 extern bool
 is_elf_object(Input_file* input_file, off_t offset,
-             const unsigned char** start, int *read_size);
+             const unsigned char** start, intread_size);
 
 // Return an Object appropriate for the input file.  P is BYTES long,
 // and holds the ELF header.  If PUNCONFIGURED is not NULL, then if
This page took 0.039491 seconds and 4 git commands to generate.