* symtab.cc (Symbol_table::add_from_relobj): Don't set the version
[deliverable/binutils-gdb.git] / gold / object.h
index a43ef0c41fac644a2794d077bb887ceb98bfd94a..4a2ad8a3679c36b7cb437641ea8c05c097faf502 100644 (file)
@@ -1,6 +1,6 @@
 // object.h -- support for an object file for linking in gold  -*- C++ -*-
 
-// Copyright 2006, 2007 Free Software Foundation, Inc.
+// Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -41,6 +41,7 @@ class Output_section;
 class Output_file;
 class Dynobj;
 class Object_merge_map;
+class Relocatable_relocs;
 
 template<typename Stringpool_char>
 class Stringpool_template;
@@ -54,31 +55,31 @@ struct Read_symbols_data
   // Section names.
   File_view* section_names;
   // Size of section name data in bytes.
-  off_t section_names_size;
+  section_size_type section_names_size;
   // Symbol data.
   File_view* symbols;
   // Size of symbol data in bytes.
-  off_t symbols_size;
+  section_size_type symbols_size;
   // Offset of external symbols within symbol data.  This structure
   // sometimes contains only external symbols, in which case this will
   // be zero.  Sometimes it contains all symbols.
-  off_t external_symbols_offset;
+  section_offset_type external_symbols_offset;
   // Symbol names.
   File_view* symbol_names;
   // Size of symbol name data in bytes.
-  off_t symbol_names_size;
+  section_size_type symbol_names_size;
 
   // Version information.  This is only used on dynamic objects.
   // Version symbol data (from SHT_GNU_versym section).
   File_view* versym;
-  off_t versym_size;
+  section_size_type versym_size;
   // Version definition data (from SHT_GNU_verdef section).
   File_view* verdef;
-  off_t verdef_size;
+  section_size_type verdef_size;
   unsigned int verdef_info;
   // Needed version data  (from SHT_GNU_verneed section).
   File_view* verneed;
-  off_t verneed_size;
+  section_size_type verneed_size;
   unsigned int verneed_info;
 };
 
@@ -110,6 +111,8 @@ struct Section_relocs
   Output_section* output_section;
   // Whether this section has special handling for offsets.
   bool needs_special_offset_handling;
+  // Whether the data section is allocated (has the SHF_ALLOC flag set).
+  bool is_data_section_allocated;
 };
 
 // Relocations in an object file.  This is read in read_relocs and
@@ -139,10 +142,10 @@ class Object
         off_t offset = 0)
     : name_(name), input_file_(input_file), offset_(offset), shnum_(-1U),
       is_dynamic_(is_dynamic), target_(NULL)
-  { }
+  { input_file->file().add_object(); }
 
   virtual ~Object()
-  { }
+  { this->input_file_->file().remove_object(); }
 
   // Return the name of the object as we would report it to the tuser.
   const std::string&
@@ -189,12 +192,17 @@ class Object
   release()
   { 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 the sized target structure associated with this object.
   // This is like the target method but it returns a pointer of
   // appropriate checked type.
   template<int size, bool big_endian>
   Sized_target<size, big_endian>*
-  sized_target(ACCEPT_SIZE_ENDIAN_ONLY) const;
+  sized_target() const;
 
   // Get the number of sections.
   unsigned int
@@ -204,10 +212,14 @@ class Object
   // Return a view of the contents of a section.  Set *PLEN to the
   // size.  CACHE is a hint as in File_read::get_view.
   const unsigned char*
-  section_contents(unsigned int shndx, off_t* plen, bool cache);
+  section_contents(unsigned int shndx, section_size_type* plen, bool cache);
 
-  // Return the name of a section given a section index.  This is only
-  // used for error messages.
+  // Return the size of a section given a section index.
+  uint64_t
+  section_size(unsigned int shndx)
+  { return this->do_section_size(shndx); }
+
+  // Return the name of a section given a section index.
   std::string
   section_name(unsigned int shndx)
   { return this->do_section_name(shndx); }
@@ -217,6 +229,11 @@ class Object
   section_flags(unsigned int shndx)
   { return this->do_section_flags(shndx); }
 
+  // Return the section address given a section index.
+  uint64_t
+  section_address(unsigned int shndx)
+  { return this->do_section_address(shndx); }
+
   // Return the section type given a section index.
   unsigned int
   section_type(unsigned int shndx)
@@ -232,6 +249,11 @@ class Object
   section_info(unsigned int shndx)
   { return this->do_section_info(shndx); }
 
+  // Return the required section alignment given a section index.
+  uint64_t
+  section_addralign(unsigned int shndx)
+  { return this->do_section_addralign(shndx); }
+
   // Read the symbol information.
   void
   read_symbols(Read_symbols_data* sd)
@@ -272,7 +294,7 @@ class Object
 
   // Return a View.
   View
-  view(off_t file_offset, off_t data_size)
+  view(off_t file_offset, section_size_type data_size)
   { return View(this->get_view(file_offset, data_size, true)); }
 
   // Report an error.
@@ -285,7 +307,7 @@ class Object
     off_t file_offset;
     off_t data_size;
 
-    Location(off_t fo, off_t ds)
+    Location(off_t fo, section_size_type ds)
       : file_offset(fo), data_size(ds)
     { }
   };
@@ -294,6 +316,37 @@ class Object
   View view(Location loc)
   { return View(this->get_view(loc.file_offset, loc.data_size, true)); }
 
+  // Get a view into the underlying file.
+  const unsigned char*
+  get_view(off_t start, section_size_type size, bool cache)
+  {
+    return this->input_file()->file().get_view(start + this->offset_, size,
+                                              cache);
+  }
+
+  // Get a lasting view into the underlying file.
+  File_view*
+  get_lasting_view(off_t start, section_size_type size, bool cache)
+  {
+    return this->input_file()->file().get_lasting_view(start + this->offset_,
+                                                      size, cache);
+  }
+
+  // Read data from the underlying file.
+  void
+  read(off_t start, section_size_type size, void* p) const
+  { this->input_file()->file().read(start + this->offset_, size, p); }
+
+  // Read multiple data from the underlying file.
+  void
+  read_multiple(const File_read::Read_multiple& rm)
+  { this->input_file()->file().read_multiple(this->offset_, rm); }
+
+  // Stop caching views in the underlying file.
+  void
+  clear_view_cache_marks()
+  { this->input_file()->file().clear_view_cache_marks(); }
+
  protected:
   // Read the symbols--implemented by child class.
   virtual void
@@ -313,6 +366,10 @@ class Object
   virtual Location
   do_section_contents(unsigned int shndx) = 0;
 
+  // Get the size of a section--implemented by child class.
+  virtual uint64_t
+  do_section_size(unsigned int shndx) = 0;
+
   // Get the name of a section--implemented by child class.
   virtual std::string
   do_section_name(unsigned int shndx) = 0;
@@ -321,6 +378,10 @@ class Object
   virtual uint64_t
   do_section_flags(unsigned int shndx) = 0;
 
+  // Get section address--implemented by child class.
+  virtual uint64_t
+  do_section_address(unsigned int shndx) = 0;
+
   // Get section type--implemented by child class.
   virtual unsigned int
   do_section_type(unsigned int shndx) = 0;
@@ -333,6 +394,10 @@ class Object
   virtual unsigned int
   do_section_info(unsigned int shndx) = 0;
 
+  // Get section alignment--implemented by child class.
+  virtual uint64_t
+  do_section_addralign(unsigned int shndx) = 0;
+
   // Get the file.  We pass on const-ness.
   Input_file*
   input_file()
@@ -342,27 +407,6 @@ class Object
   input_file() const
   { return this->input_file_; }
 
-  // Get a view into the underlying file.
-  const unsigned char*
-  get_view(off_t start, off_t size, bool cache)
-  {
-    return this->input_file()->file().get_view(start + this->offset_, size,
-                                              cache);
-  }
-
-  // Get a lasting view into the underlying file.
-  File_view*
-  get_lasting_view(off_t start, off_t size, bool cache)
-  {
-    return this->input_file()->file().get_lasting_view(start + this->offset_,
-                                                      size, cache);
-  }
-
-  // Read data from the underlying file.
-  void
-  read(off_t start, off_t size, void* p) const
-  { this->input_file()->file().read(start + this->offset_, size, p); }
-
   // Set the target.
   void
   set_target(int machine, int size, bool big_endian, int osabi,
@@ -413,7 +457,7 @@ class Object
 
 template<int size, bool big_endian>
 inline Sized_target<size, big_endian>*
-Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY) const
+Object::sized_target() const
 {
   gold_assert(this->target_->get_size() == size);
   gold_assert(this->target_->is_big_endian() ? big_endian : !big_endian);
@@ -429,6 +473,7 @@ class Relobj : public Object
   Relobj(const std::string& name, Input_file* input_file, off_t offset = 0)
     : Object(name, input_file, false, offset),
       map_to_output_(),
+      map_to_relocatable_relocs_(NULL),
       object_merge_map_(NULL),
       relocs_must_follow_section_writes_(false)
   { }
@@ -504,11 +549,11 @@ class Relobj : public Object
   // and set *POFF to the offset within that section.  *POFF will be
   // set to -1 if the section requires special handling.
   inline Output_section*
-  output_section(unsigned int shndx, off_t* poff) const;
+  output_section(unsigned int shndx, section_offset_type* poff) const;
 
   // Set the offset of an input section within its output section.
   void
-  set_section_offset(unsigned int shndx, off_t off)
+  set_section_offset(unsigned int shndx, section_offset_type off)
   {
     gold_assert(shndx < this->map_to_output_.size());
     this->map_to_output_[shndx].offset = off;
@@ -535,6 +580,22 @@ class Relobj : public Object
     this->object_merge_map_ = object_merge_map;
   }
 
+  // Record the relocatable reloc info for an input reloc section.
+  void
+  set_relocatable_relocs(unsigned int reloc_shndx, Relocatable_relocs* rr)
+  {
+    gold_assert(reloc_shndx < this->shnum());
+    (*this->map_to_relocatable_relocs_)[reloc_shndx] = rr;
+  }
+
+  // Get the relocatable reloc info for an input reloc section.
+  Relocatable_relocs*
+  relocatable_relocs(unsigned int reloc_shndx)
+  {
+    gold_assert(reloc_shndx < this->shnum());
+    return (*this->map_to_relocatable_relocs_)[reloc_shndx];
+  }
+
  protected:
   // What we need to know to map an input section to an output
   // section.  We keep an array of these, one for each input section,
@@ -546,7 +607,7 @@ class Relobj : public Object
     Output_section* output_section;
     // The offset within the output section.  This is -1 if the
     // section requires special handling.
-    off_t offset;
+    section_offset_type offset;
   };
 
   // Read the relocs--implemented by child class.
@@ -565,10 +626,11 @@ class Relobj : public Object
   // Count local symbols--implemented by child class.
   virtual void
   do_count_local_symbols(Stringpool_template<char>*,
-                           Stringpool_template<char>*) = 0;
+                        Stringpool_template<char>*) = 0;
 
-  // Finalize the local symbols.  Set the output symbol table indexes for the local variables, and set the
-  // offset where local symbol information will be stored.
+  // Finalize the local symbols.  Set the output symbol table indexes
+  // for the local variables, and set the offset where local symbol
+  // information will be stored.
   virtual unsigned int
   do_finalize_local_symbols(unsigned int, off_t) = 0;
 
@@ -595,6 +657,14 @@ class Relobj : public Object
   map_to_output() const
   { return this->map_to_output_; }
 
+  // Set the size of the relocatable relocs array.
+  void
+  size_relocatable_relocs()
+  {
+    this->map_to_relocatable_relocs_ =
+      new std::vector<Relocatable_relocs*>(this->shnum());
+  }
+
   // Record that we must wait for the output sections to be written
   // before applying relocations.
   void
@@ -604,6 +674,9 @@ class Relobj : public Object
  private:
   // Mapping from input sections to output section.
   std::vector<Map_to_output> map_to_output_;
+  // Mapping from input section index to the information recorded for
+  // the relocations.  This is only used for a relocatable link.
+  std::vector<Relocatable_relocs*>* map_to_relocatable_relocs_;
   // Mappings for merge sections.  This is managed by the code in the
   // Merge_map class.
   Object_merge_map* object_merge_map_;
@@ -614,7 +687,7 @@ class Relobj : public Object
 
 // Implement Object::output_section inline for efficiency.
 inline Output_section*
-Relobj::output_section(unsigned int shndx, off_t* poff) const
+Relobj::output_section(unsigned int shndx, section_offset_type* poff) const
 {
   gold_assert(shndx < this->map_to_output_.size());
   const Map_to_output& mo(this->map_to_output_[shndx]);
@@ -622,6 +695,71 @@ Relobj::output_section(unsigned int shndx, off_t* poff) const
   return mo.output_section;
 }
 
+// This class is used to handle relocations against a section symbol
+// in an SHF_MERGE section.  For such a symbol, we need to know the
+// addend of the relocation before we can determine the final value.
+// The addend gives us the location in the input section, and we can
+// determine how it is mapped to the output section.  For a
+// non-section symbol, we apply the addend to the final value of the
+// symbol; that is done in finalize_local_symbols, and does not use
+// this class.
+
+template<int size>
+class Merged_symbol_value
+{
+ public:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Value;
+
+  // We use a hash table to map offsets in the input section to output
+  // addresses.
+  typedef Unordered_map<section_offset_type, Value> Output_addresses;
+
+  Merged_symbol_value(Value input_value, Value output_start_address)
+    : input_value_(input_value), output_start_address_(output_start_address),
+      output_addresses_()
+  { }
+
+  // Initialize the hash table.
+  void
+  initialize_input_to_output_map(const Relobj*, unsigned int input_shndx);
+
+  // Release the hash table to save space.
+  void
+  free_input_to_output_map()
+  { this->output_addresses_.clear(); }
+
+  // Get the output value corresponding to an addend.  The object and
+  // input section index are passed in because the caller will have
+  // them; otherwise we could store them here.
+  Value
+  value(const Relobj* object, unsigned int input_shndx, Value addend) const
+  {
+    Value input_offset = this->input_value_ + addend;
+    typename Output_addresses::const_iterator p =
+      this->output_addresses_.find(input_offset);
+    if (p != this->output_addresses_.end())
+      return p->second;
+
+    return this->value_from_output_section(object, input_shndx, input_offset);
+  }
+
+ private:
+  // Get the output value for an input offset if we couldn't find it
+  // in the hash table.
+  Value
+  value_from_output_section(const Relobj*, unsigned int input_shndx,
+                           Value input_offset) const;
+
+  // The value of the section symbol in the input file.  This is
+  // normally zero, but could in principle be something else.
+  Value input_value_;
+  // The start address of this merged section in the output file.
+  Value output_start_address_;
+  // A hash table which maps offsets in the input section to output
+  // addresses.  This only maps specific offsets, not all offsets.
+  Output_addresses output_addresses_;
+};
+
 // This POD class is holds the value of a symbol.  This is used for
 // local symbols, and for all symbols during relocation processing.
 // For special sections, such as SHF_MERGE sections, this calls a
@@ -636,8 +774,8 @@ class Symbol_value
   Symbol_value()
     : output_symtab_index_(0), output_dynsym_index_(-1U), input_shndx_(0),
       is_section_symbol_(false), is_tls_symbol_(false),
-      needs_output_address_(false), value_(0)
-  { }
+      has_output_value_(true)
+  { this->u_.value = 0; }
 
   // 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.
@@ -645,41 +783,64 @@ class Symbol_value
   Value
   value(const Sized_relobj<size, big_endian>* object, Value addend) const
   {
-    if (!this->needs_output_address_)
-      return this->value_ + addend;
-    return object->local_value(this->input_shndx_, this->value_,
-                              this->is_section_symbol_, addend);
+    if (this->has_output_value_)
+      return this->u_.value + addend;
+    else
+      return this->u_.merged_symbol_value->value(object, this->input_shndx_,
+                                                addend);
   }
 
   // Set the value of this symbol in the output symbol table.
   void
   set_output_value(Value value)
+  { this->u_.value = value; }
+
+  // For a section symbol in a merged section, we need more
+  // information.
+  void
+  set_merged_symbol_value(Merged_symbol_value<size>* msv)
   {
-    this->value_ = value;
-    this->needs_output_address_ = false;
+    gold_assert(this->is_section_symbol_);
+    this->has_output_value_ = false;
+    this->u_.merged_symbol_value = msv;
   }
 
-  // Set the value of the symbol from the input file.  This value
-  // will usually be replaced during finalization with the output
-  // value, but if the symbol is mapped to an output section which
-  // requires special handling to determine the output value, we
-  // leave the input value in place until later.  This is used for
-  // SHF_MERGE sections.
+  // Initialize the input to output map for a section symbol in a
+  // merged section.  We also initialize the value of a non-section
+  // symbol in a merged section.
   void
-  set_input_value(Value value)
+  initialize_input_to_output_map(const Relobj* object)
   {
-    this->value_ = value;
-    this->needs_output_address_ = true;
+    if (!this->has_output_value_)
+      {
+       gold_assert(this->is_section_symbol_);
+       Merged_symbol_value<size>* msv = this->u_.merged_symbol_value;
+       msv->initialize_input_to_output_map(object, this->input_shndx_);
+      }
   }
 
-  // Return the input value.
-  Value
-  input_value() const
+  // Free the input to output map for a section symbol in a merged
+  // section.
+  void
+  free_input_to_output_map()
   {
-    gold_assert(this->needs_output_address_);
-    return this->value_;
+    if (!this->has_output_value_)
+      this->u_.merged_symbol_value->free_input_to_output_map();
   }
 
+  // Set the value of the symbol from the input file.  This is only
+  // called by count_local_symbols, to communicate the value to
+  // finalize_local_symbols.
+  void
+  set_input_value(Value value)
+  { this->u_.value = value; }
+
+  // Return the input value.  This is only called by
+  // finalize_local_symbols.
+  Value
+  input_value() const
+  { return this->u_.value; }
+
   // Return whether this symbol should go into the output symbol
   // table.
   bool
@@ -715,6 +876,7 @@ class Symbol_value
   void
   set_needs_output_dynsym_entry()
   {
+    gold_assert(!this->is_section_symbol());
     this->output_dynsym_index_ = 0;
   }
 
@@ -738,7 +900,8 @@ class Symbol_value
   unsigned int
   output_dynsym_index() const
   {
-    gold_assert(this->output_dynsym_index_ != 0);
+    gold_assert(this->output_dynsym_index_ != 0
+                && this->output_dynsym_index_ != -1U);
     return this->output_dynsym_index_;
   }
 
@@ -757,10 +920,18 @@ class Symbol_value
   input_shndx() const
   { return this->input_shndx_; }
 
+  // Whether this is a section symbol.
+  bool
+  is_section_symbol() const
+  { return this->is_section_symbol_; }
+
   // Record that this is a section symbol.
   void
   set_is_section_symbol()
-  { this->is_section_symbol_ = true; }
+  {
+    gold_assert(!this->needs_output_dynsym_entry());
+    this->is_section_symbol_ = true;
+  }
 
   // Record that this is a TLS symbol.
   void
@@ -786,14 +957,100 @@ class Symbol_value
   bool is_section_symbol_ : 1;
   // Whether this is a STT_TLS symbol.
   bool is_tls_symbol_ : 1;
-  // Whether getting the value of this symbol requires calling an
-  // Output_section method.  For example, this will be true of a
-  // symbol in a SHF_MERGE section.
-  bool needs_output_address_ : 1;
-  // The value of the symbol.  If !needs_output_address_, this is the
-  // value in the output file.  If needs_output_address_, this is the
-  // value in the input file.
-  Value value_;
+  // 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
+  // a merge section, as for such symbols we can not determine the
+  // value to use in a relocation until we see the addend.
+  bool has_output_value_ : 1;
+  union
+  {
+    // This is used if has_output_value_ is true.  Between
+    // count_local_symbols and finalize_local_symbols, this is the
+    // value in the input file.  After finalize_local_symbols, it is
+    // the value in the output file.
+    Value value;
+    // This is used if has_output_value_ is false.  It points to the
+    // information we need to get the value for a merge section.
+    Merged_symbol_value<size>* merged_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_;
 };
 
 // A regular object file.  This is size and endian specific.
@@ -863,27 +1120,20 @@ class Sized_relobj : public Relobj
     return this->local_values_[sym].output_dynsym_index();
   }
 
-  // Return the appropriate Sized_target structure.
-  Sized_target<size, big_endian>*
-  sized_target()
+  // Return the input section index of local symbol SYM.
+  unsigned int
+  local_symbol_input_shndx(unsigned int sym) const
   {
-    return this->Object::sized_target
-      SELECT_SIZE_ENDIAN_NAME(size, big_endian) (
-          SELECT_SIZE_ENDIAN_ONLY(size, big_endian));
+    gold_assert(sym < this->local_values_.size());
+    return this->local_values_[sym].input_shndx();
   }
 
-  // Return the value of the local symbol symndx.
-  Address
-  local_symbol_value(unsigned int symndx) const;
-
-  // Return the value of a local symbol defined in input section
-  // SHNDX, with value VALUE, adding addend ADDEND.  IS_SECTION_SYMBOL
-  // indicates whether the symbol is a section symbol.  This handles
-  // SHF_MERGE sections.
-  Address
-  local_value(unsigned int shndx, Address value, bool is_section_symbol,
-             Address addend) const;
+  // Return the appropriate Sized_target structure.
+  Sized_target<size, big_endian>*
+  sized_target()
+  { return this->Object::sized_target<size, big_endian>(); }
 
+  // Record that local symbol SYM needs a dynamic symbol entry.
   void
   set_needs_output_dynsym_entry(unsigned int sym)
   {
@@ -894,84 +1144,40 @@ class Sized_relobj : public Relobj
   // Return whether the local symbol SYMNDX has a GOT offset.
   // For TLS symbols, the GOT entry will hold its tp-relative offset.
   bool
-  local_has_got_offset(unsigned int symndx) const
+  local_has_got_offset(unsigned int symndx, unsigned int got_type) const
   {
-    return (this->local_got_offsets_.find(symndx)
-            != this->local_got_offsets_.end());
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    return (p != this->local_got_offsets_.end()
+            && p->second->get_offset(got_type) != -1U);
   }
 
   // Return the GOT offset of the local symbol SYMNDX.
   unsigned int
-  local_got_offset(unsigned int symndx) const
+  local_got_offset(unsigned int symndx, unsigned int got_type) const
   {
     Local_got_offsets::const_iterator p =
         this->local_got_offsets_.find(symndx);
     gold_assert(p != this->local_got_offsets_.end());
-    return p->second;
+    unsigned int off = p->second->get_offset(got_type);
+    gold_assert(off != -1U);
+    return off;
   }
 
   // Set the GOT offset of the local symbol SYMNDX to GOT_OFFSET.
   void
-  set_local_got_offset(unsigned int symndx, unsigned int got_offset)
-  {
-    std::pair<Local_got_offsets::iterator, bool> ins =
-        this->local_got_offsets_.insert(std::make_pair(symndx, got_offset));
-    gold_assert(ins.second);
-  }
-
-  // Return whether the local TLS symbol SYMNDX has a GOT offset.
-  // The GOT entry at this offset will contain a module index. If
-  // NEED_PAIR is true, a second entry immediately following the first
-  // will contain the dtv-relative offset.
-  bool
-  local_has_tls_got_offset(unsigned int symndx, bool need_pair) const
+  set_local_got_offset(unsigned int symndx, unsigned int got_type,
+                       unsigned int got_offset)
   {
-    typename Local_tls_got_offsets::const_iterator p =
-        this->local_tls_got_offsets_.find(symndx);
-    if (p == this->local_tls_got_offsets_.end()
-        || (need_pair && !p->second.have_pair_))
-      return false;
-    return true;
-  }
-
-  // Return the offset of the GOT entry for the local TLS symbol SYMNDX.
-  // If NEED_PAIR is true, we need the offset of a pair of GOT entries;
-  // otherwise we need the offset of the GOT entry for the module index.
-  unsigned int
-  local_tls_got_offset(unsigned int symndx, bool need_pair) const
-  {
-    typename Local_tls_got_offsets::const_iterator p =
-        this->local_tls_got_offsets_.find(symndx);
-    gold_assert(p != this->local_tls_got_offsets_.end());
-    gold_assert(!need_pair || p->second.have_pair_);
-    return p->second.got_offset_;
-  }
-
-  // Set the offset of the GOT entry for the local TLS symbol SYMNDX
-  // to GOT_OFFSET. If HAVE_PAIR is true, we have a pair of GOT entries;
-  // otherwise, we have just a single entry for the module index.
-  void
-  set_local_tls_got_offset(unsigned int symndx, unsigned int got_offset,
-                           bool have_pair)
-  {
-    typename Local_tls_got_offsets::iterator p =
-        this->local_tls_got_offsets_.find(symndx);
-    if (p != this->local_tls_got_offsets_.end())
-      {
-        // An entry already existed for this symbol. This can happen
-        // if we see a relocation asking for the module index before
-        // a relocation asking for the pair. In that case, the original
-        // GOT entry will remain, but won't get used by any further
-        // relocations.
-        p->second.got_offset_ = got_offset;
-       gold_assert(have_pair);
-        p->second.have_pair_ = true;
-      }
+    Local_got_offsets::const_iterator p =
+        this->local_got_offsets_.find(symndx);
+    if (p != this->local_got_offsets_.end())
+      p->second->set_offset(got_type, got_offset);
     else
       {
-        std::pair<typename Local_tls_got_offsets::iterator, bool> ins =
-            this->local_tls_got_offsets_.insert(
-              std::make_pair(symndx, Tls_got_entry(got_offset, have_pair)));
+        Got_offset_list* g = new Got_offset_list(got_type, got_offset);
+        std::pair<Local_got_offsets::iterator, bool> ins =
+            this->local_got_offsets_.insert(std::make_pair(symndx, g));
         gold_assert(ins.second);
       }
   }
@@ -1032,6 +1238,11 @@ class Sized_relobj : public Relobj
   do_relocate(const General_options& options, const Symbol_table* symtab,
              const Layout*, Output_file* of);
 
+  // Get the size of a section.
+  uint64_t
+  do_section_size(unsigned int shndx)
+  { return this->elf_file_.section_size(shndx); }
+
   // Get the name of a section.
   std::string
   do_section_name(unsigned int shndx)
@@ -1047,6 +1258,11 @@ class Sized_relobj : public Relobj
   do_section_flags(unsigned int shndx)
   { return this->elf_file_.section_flags(shndx); }
 
+  // Return section address.
+  uint64_t
+  do_section_address(unsigned int shndx)
+  { return this->elf_file_.section_addr(shndx); }
+
   // Return section type.
   unsigned int
   do_section_type(unsigned int shndx)
@@ -1062,6 +1278,11 @@ class Sized_relobj : public Relobj
   do_section_info(unsigned int shndx)
   { return this->elf_file_.section_info(shndx); }
 
+  // Return the section alignment.
+  uint64_t
+  do_section_addralign(unsigned int shndx)
+  { return this->elf_file_.section_addralign(shndx); }
+
  private:
   // For convenience.
   typedef Sized_relobj<size, big_endian> This;
@@ -1083,11 +1304,11 @@ class Sized_relobj : public Relobj
   // a GNU style exception frame section.
   bool
   find_eh_frame(const unsigned char* pshdrs, const char* names,
-               off_t names_size) const;
+               section_size_type names_size) const;
 
   // Whether to include a section group in the link.
   bool
-  include_section_group(Layout*, unsigned int,
+  include_section_group(Symbol_table*, Layout*, unsigned int, const char*,
                        const elfcpp::Shdr<size, big_endian>&,
                        std::vector<bool>*);
 
@@ -1102,7 +1323,7 @@ class Sized_relobj : public Relobj
     unsigned char* view;
     typename elfcpp::Elf_types<size>::Elf_Addr address;
     off_t offset;
-    off_t view_size;
+    section_size_type view_size;
     bool is_input_output_view;
     bool is_postprocessing_view;
   };
@@ -1112,22 +1333,76 @@ class Sized_relobj : public Relobj
   // Write section data to the output file.  Record the views and
   // sizes in VIEWS for use when relocating.
   void
-  write_sections(const unsigned char* pshdrs, Output_file*, Views*) const;
+  write_sections(const unsigned char* pshdrs, Output_file*, Views*);
 
   // Relocate the sections in the output file.
   void
   relocate_sections(const General_options& options, const Symbol_table*,
                    const Layout*, const unsigned char* pshdrs, Views*);
 
+  // Scan the input relocations for --emit-relocs.
+  void
+  emit_relocs_scan(const General_options&, Symbol_table*, Layout*,
+                  const unsigned char* plocal_syms,
+                  const Read_relocs_data::Relocs_list::iterator&);
+
+  // Scan the input relocations for --emit-relocs, templatized on the
+  // type of the relocation section.
+  template<int sh_type>
+  void
+  emit_relocs_scan_reltype(const General_options&, Symbol_table*, Layout*,
+                          const unsigned char* plocal_syms,
+                          const Read_relocs_data::Relocs_list::iterator&,
+                          Relocatable_relocs*);
+
+  // Emit the relocs for --emit-relocs.
+  void
+  emit_relocs(const Relocate_info<size, big_endian>*, unsigned int,
+             unsigned int sh_type, const unsigned char* prelocs,
+             size_t reloc_count, Output_section*, off_t output_offset,
+             unsigned char* view, Address address,
+             section_size_type view_size,
+             unsigned char* reloc_view, section_size_type reloc_view_size);
+
+  // Emit the relocs for --emit-relocs, templatized on the type of the
+  // relocation section.
+  template<int sh_type>
+  void
+  emit_relocs_reltype(const Relocate_info<size, big_endian>*, unsigned int,
+                     const unsigned char* prelocs, size_t reloc_count,
+                     Output_section*, off_t output_offset,
+                     unsigned char* view, Address address,
+                     section_size_type view_size,
+                     unsigned char* reloc_view,
+                     section_size_type reloc_view_size);
+
+  // Initialize input to output maps for section symbols in merged
+  // sections.
+  void
+  initialize_input_to_output_maps();
+
+  // Free the input to output maps for section symbols in merged
+  // sections.
+  void
+  free_input_to_output_maps();
+
   // Write out the local symbols.
   void
   write_local_symbols(Output_file*,
                      const Stringpool_template<char>*,
                      const Stringpool_template<char>*);
 
+  // Clear the local symbol information.
+  void
+  clear_local_symbols()
+  {
+    this->local_values_.clear();
+    this->local_got_offsets_.clear();
+  }
+
   // The GOT offsets of local symbols. This map also stores GOT offsets
   // for tp-relative offsets for TLS symbols.
-  typedef Unordered_map<unsigned int, unsigned int> Local_got_offsets;
+  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
@@ -1166,9 +1441,6 @@ 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_;
-  // GOT offsets for local TLS symbols, indexed by symbol number
-  // and GOT entry type.
-  Local_tls_got_offsets local_tls_got_offsets_;
   // Whether this object has a GNU style .eh_frame section.
   bool has_eh_frame_;
 };
@@ -1179,8 +1451,7 @@ class Input_objects
 {
  public:
   Input_objects()
-    : relobj_list_(), dynobj_list_(), target_(NULL), sonames_(),
-      system_library_directory_()
+    : relobj_list_(), dynobj_list_(), sonames_(), system_library_directory_()
   { }
 
   // The type of the list of input relocateable objects.
@@ -1196,11 +1467,6 @@ class Input_objects
   bool
   add_object(Object*);
 
-  // Get the target we should use for the output file.
-  Target*
-  target() const
-  { return this->target_; }
-
   // For each dynamic object, check whether we've seen all of its
   // explicit dependencies.
   void
@@ -1249,8 +1515,6 @@ class Input_objects
   Relobj_list relobj_list_;
   // The list of dynamic objects included in the link.
   Dynobj_list dynobj_list_;
-  // The target.
-  Target* target_;
   // SONAMEs that we have seen.
   Unordered_set<std::string> sonames_;
   // The directory in which we find the libc.so.
@@ -1288,7 +1552,7 @@ struct Relocate_info
 extern Object*
 make_elf_object(const std::string& name, Input_file*,
                off_t offset, const unsigned char* p,
-               off_t bytes);
+               section_offset_type bytes);
 
 } // end namespace gold
 
This page took 0.03358 seconds and 4 git commands to generate.