Fix problem where mixed section types can cause internal error during a -r link.
[deliverable/binutils-gdb.git] / gold / object.h
index f796fb501470e38039c3f535fbd10786da91a02a..9fb9b306280c0fad0b4d234f862d5b347d81ed12 100644 (file)
@@ -1,6 +1,6 @@
 // object.h -- support for an object file for linking in gold  -*- C++ -*-
 
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2018 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -315,6 +315,57 @@ class Got_offset_list
   Got_offset_list* got_next_;
 };
 
+// The Local_got_entry_key used to index the GOT offsets for local
+// non-TLS symbols, and tp-relative offsets for TLS symbols.
+
+class Local_got_entry_key
+{
+ public:
+  Local_got_entry_key(unsigned int symndx, uint64_t addend)
+    : symndx_(symndx), addend_(addend)
+  {}
+
+  // Whether this equals to another Local_got_entry_key.
+  bool
+  eq(const Local_got_entry_key& key) const
+  {
+    return (this->symndx_ == key.symndx_ && this->addend_ == key.addend_);
+  }
+
+  // Compute a hash value for this using 64-bit FNV-1a hash.
+  size_t
+  hash_value() const
+  {
+    uint64_t h = 14695981039346656037ULL; // FNV offset basis.
+    uint64_t prime = 1099511628211ULL;
+    h = (h ^ static_cast<uint64_t>(this->symndx_)) * prime;
+    h = (h ^ static_cast<uint64_t>(this->addend_)) * prime;
+    return h;
+  }
+
+  // Functors for associative containers.
+  struct equal_to
+  {
+    bool
+    operator()(const Local_got_entry_key& key1,
+               const Local_got_entry_key& key2) const
+    { return key1.eq(key2); }
+  };
+
+  struct hash
+  {
+    size_t
+    operator()(const Local_got_entry_key& key) const
+    { return key.hash_value(); }
+  };
+
+ private:
+  // The local symbol index.
+  unsigned int symndx_;
+  // The addend.
+  uint64_t addend_;
+};
+
 // Type for mapping section index to uncompressed size and contents.
 
 struct Compressed_section_info
@@ -793,6 +844,11 @@ class Object
   get_incremental_reloc_count(unsigned int symndx) const
   { return this->do_get_incremental_reloc_count(symndx); }
 
+  // Return the output view for section SHNDX.
+  unsigned char*
+  get_output_view(unsigned int shndx, section_size_type* plen) const
+  { return this->do_get_output_view(shndx, plen); }
+
  protected:
   // Returns NULL for Objects that are not dynamic objects.  This method
   // is overridden in the Dynobj class.
@@ -978,6 +1034,11 @@ class Object
   do_get_incremental_reloc_count(unsigned int) const
   { gold_unreachable(); }
 
+  // Return the output view for a section.
+  virtual unsigned char*
+  do_get_output_view(unsigned int, section_size_type*) const
+  { gold_unreachable(); }
+
   void
   set_compressed_sections(Compressed_section_map* compressed_sections)
   { this->compressed_sections_ = compressed_sections; }
@@ -1111,21 +1172,43 @@ class Relobj : public Object
   // GOT_TYPE.
   bool
   local_has_got_offset(unsigned int symndx, unsigned int got_type) const
-  { return this->do_local_has_got_offset(symndx, got_type); }
+  { return this->do_local_has_got_offset(symndx, got_type, 0); }
+
+  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
+  // of type GOT_TYPE.
+  bool
+  local_has_got_offset(unsigned int symndx, unsigned int got_type,
+                      uint64_t addend) const
+  { return this->do_local_has_got_offset(symndx, got_type, addend); }
 
   // Return the GOT offset of type GOT_TYPE of the local symbol
   // SYMNDX.  It is an error to call this if the symbol does not have
   // a GOT offset of the specified type.
   unsigned int
   local_got_offset(unsigned int symndx, unsigned int got_type) const
-  { return this->do_local_got_offset(symndx, got_type); }
+  { return this->do_local_got_offset(symndx, got_type, 0); }
+
+  // Return the GOT offset of type GOT_TYPE of the local symbol
+  // SYMNDX plus ADDEND.  It is an error to call this if the symbol
+  // does not have a GOT offset of the specified type.
+  unsigned int
+  local_got_offset(unsigned int symndx, unsigned int got_type,
+                      uint64_t addend) const
+  { return this->do_local_got_offset(symndx, got_type, addend); }
 
   // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
   // to GOT_OFFSET.
   void
   set_local_got_offset(unsigned int symndx, unsigned int got_type,
                       unsigned int got_offset)
-  { this->do_set_local_got_offset(symndx, got_type, got_offset); }
+  { this->do_set_local_got_offset(symndx, got_type, got_offset, 0); }
+
+  // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
+  // plus ADDEND to GOT_OFFSET.
+  void
+  set_local_got_offset(unsigned int symndx, unsigned int got_type,
+                      unsigned int got_offset, uint64_t addend)
+  { this->do_set_local_got_offset(symndx, got_type, got_offset, addend); }
 
   // Return whether the local symbol SYMNDX is a TLS symbol.
   bool
@@ -1318,19 +1401,21 @@ class Relobj : public Object
   virtual unsigned int
   do_local_plt_offset(unsigned int symndx) const = 0;
 
-  // Return whether a local symbol has a GOT offset of a given type.
+  // Return whether a local symbol plus addend has a GOT offset
+  // of a given type.
   virtual bool
   do_local_has_got_offset(unsigned int symndx,
-                         unsigned int got_type) const = 0;
+                         unsigned int got_type, uint64_t addend) const = 0;
 
-  // Return the GOT offset of a given type of a local symbol.
+  // Return the GOT offset of a given type of a local symbol plus addend.
   virtual unsigned int
-  do_local_got_offset(unsigned int symndx, unsigned int got_type) const = 0;
+  do_local_got_offset(unsigned int symndx, unsigned int got_type,
+                     uint64_t addend) const = 0;
 
-  // Set the GOT offset with a given type for a local symbol.
+  // Set the GOT offset with a given type for a local symbol plus addend.
   virtual void
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
-                         unsigned int got_offset) = 0;
+                         unsigned int got_offset, uint64_t addend) = 0;
 
   // Return whether local symbol SYMNDX is a TLS symbol.
   virtual bool
@@ -1993,24 +2078,28 @@ class Sized_relobj : public Relobj
        : convert_types<Address, uint64_t>(off));
   }
 
-  // Return whether the local symbol SYMNDX has a GOT offset of type
-  // GOT_TYPE.
+  // Return whether the local symbol SYMNDX plus ADDEND has a GOT offset
+  // of type GOT_TYPE.
   bool
-  do_local_has_got_offset(unsigned int symndx, unsigned int got_type) const
+  do_local_has_got_offset(unsigned int symndx, unsigned int got_type,
+                         uint64_t addend) const
   {
+    Local_got_entry_key key(symndx, addend);
     Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     return (p != this->local_got_offsets_.end()
             && p->second->get_offset(got_type) != -1U);
   }
 
   // Return the GOT offset of type GOT_TYPE of the local symbol
-  // SYMNDX.
+  // SYMNDX plus ADDEND.
   unsigned int
-  do_local_got_offset(unsigned int symndx, unsigned int got_type) const
+  do_local_got_offset(unsigned int symndx, unsigned int got_type,
+                         uint64_t addend) const
   {
+    Local_got_entry_key key(symndx, addend);
     Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     gold_assert(p != this->local_got_offsets_.end());
     unsigned int off = p->second->get_offset(got_type);
     gold_assert(off != -1U);
@@ -2018,20 +2107,21 @@ class Sized_relobj : public Relobj
   }
 
   // Set the GOT offset with type GOT_TYPE of the local symbol SYMNDX
-  // to GOT_OFFSET.
+  // plus ADDEND to GOT_OFFSET.
   void
   do_set_local_got_offset(unsigned int symndx, unsigned int got_type,
-                         unsigned int got_offset)
+                         unsigned int got_offset, uint64_t addend)
   {
+    Local_got_entry_key key(symndx, addend);
     Local_got_offsets::const_iterator p =
-        this->local_got_offsets_.find(symndx);
+        this->local_got_offsets_.find(key);
     if (p != this->local_got_offsets_.end())
       p->second->set_offset(got_type, got_offset);
     else
       {
         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));
+            this->local_got_offsets_.insert(std::make_pair(key, g));
         gold_assert(ins.second);
       }
   }
@@ -2049,10 +2139,12 @@ class Sized_relobj : public Relobj
  private:
   // 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;
+  typedef Unordered_map<Local_got_entry_key, Got_offset_list*,
+                        Local_got_entry_key::hash,
+                        Local_got_entry_key::equal_to> Local_got_offsets;
 
   // GOT offsets for local non-TLS symbols, and tp-relative offsets
-  // for TLS symbols, indexed by symbol number.
+  // for TLS symbols, indexed by local got entry key class.
   Local_got_offsets local_got_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
@@ -2470,6 +2562,13 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                       const unsigned char* pshdrs, Output_file* of,
                       Views* pviews);
 
+  // Relocate section data for a range of sections.
+  void
+  relocate_section_range(const Symbol_table* symtab, const Layout* layout,
+                        const unsigned char* pshdrs, Output_file* of,
+                        Views* pviews, unsigned int start_shndx,
+                        unsigned int end_shndx);
+
   // Adjust this local symbol value.  Return false if the symbol
   // should be discarded from the output file.
   virtual bool
@@ -2481,6 +2580,10 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   set_output_local_symbol_count(unsigned int value)
   { this->output_local_symbol_count_ = value; }
 
+  // Return the output view for a section.
+  unsigned char*
+  do_get_output_view(unsigned int, section_size_type*) const;
+
  private:
   // For convenience.
   typedef Sized_relobj_file<size, big_endian> This;
@@ -2488,6 +2591,7 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
   static const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
   typedef elfcpp::Shdr<size, big_endian> Shdr;
+  typedef elfcpp::Shdr_write<size, big_endian> Shdr_write;
 
   // To keep track of discarded comdat sections, we need to map a member
   // section index to the object and section index of the corresponding
@@ -2532,8 +2636,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   // Layout an input section.
   void
   layout_section(Layout* layout, unsigned int shndx, const char* name,
-                 const typename This::Shdr& shdr, unsigned int reloc_shndx,
-                 unsigned int reloc_type);
+                 const typename This::Shdr& shdr, unsigned int sh_type,
+                 unsigned int reloc_shndx, unsigned int reloc_type);
 
   // Layout an input .eh_frame section.
   void
@@ -2614,7 +2718,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                     unsigned int sh_type, unsigned int shndx,
                     const unsigned char* prelocs, size_t reloc_count,
                     unsigned char* view, section_size_type view_size,
-                    Reloc_symbol_changes** reloc_map);
+                    Reloc_symbol_changes** reloc_map,
+                    const Sized_target<size, big_endian>* target);
 
   template<int sh_type>
   void
@@ -2622,7 +2727,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
                             unsigned int shndx, const unsigned char* prelocs,
                             size_t reloc_count, unsigned char* view,
                             section_size_type view_size,
-                            Reloc_symbol_changes** reloc_map);
+                            Reloc_symbol_changes** reloc_map,
+                            const Sized_target<size, big_endian>* target);
 
   // Find all functions in a section.
   void
@@ -2693,15 +2799,18 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   {
     static const int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
     Deferred_layout(unsigned int shndx, const char* name,
+                    unsigned int sh_type,
                     const unsigned char* pshdr,
                     unsigned int reloc_shndx, unsigned int reloc_type)
-      : shndx_(shndx), name_(name), reloc_shndx_(reloc_shndx),
+      : name_(name), shndx_(shndx), reloc_shndx_(reloc_shndx),
         reloc_type_(reloc_type)
     {
+      typename This::Shdr_write shdr(this->shdr_data_);
       memcpy(this->shdr_data_, pshdr, shdr_size);
+      shdr.put_sh_type(sh_type);
     }
-    unsigned int shndx_;
     std::string name_;
+    unsigned int shndx_;
     unsigned int reloc_shndx_;
     unsigned int reloc_type_;
     unsigned char shdr_data_[shdr_size];
@@ -2737,9 +2846,6 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   Kept_comdat_section_table kept_comdat_sections_;
   // Whether this object has a GNU style .eh_frame section.
   bool has_eh_frame_;
-  // If this object has a GNU style .eh_frame section that is discarded in
-  // output, record the index here.  Otherwise it is -1U.
-  unsigned int discarded_eh_frame_shndx_;
   // True if the layout of this object was deferred, waiting for plugin
   // replacement files.
   bool is_deferred_layout_;
@@ -2747,6 +2853,8 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian>
   std::vector<Deferred_layout> deferred_layout_;
   // The list of relocation sections whose layout was deferred.
   std::vector<Deferred_layout> deferred_layout_relocs_;
+  // Pointer to the list of output views; valid only during do_relocate().
+  const Views* output_views_;
 };
 
 // A class to manage the list of all objects.
@@ -2862,6 +2970,8 @@ struct Relocate_info
   unsigned int reloc_shndx;
   // Section header of relocation section.
   const unsigned char* reloc_shdr;
+  // Info about how relocs should be handled
+  Relocatable_relocs* rr;
   // Section index of section being relocated.
   unsigned int data_shndx;
   // Section header of data section.
This page took 0.027423 seconds and 4 git commands to generate.