merge from gcc
[deliverable/binutils-gdb.git] / gold / reloc.h
index 7829440bf49ecb21f2d8529919a67843e45df371..1edaa579ceed403c0adfc4894aa00bcc07ce1420 100644 (file)
@@ -17,6 +17,12 @@ class Stringpool;
 class Symbol;
 class Layout;
 
+template<int size>
+class Sized_symbol;
+
+template<int sh_type, bool dynamic, int size, bool big_endian>
+class Output_data_reloc;
+
 // A class to read the relocations for an object file, and then queue
 // up a task to see if they require any GOT/PLT/COPY relocations in
 // the symbol table.
@@ -229,12 +235,99 @@ public:
   {
     This::template pcrel<64>(view, value, address);
   }
+};
+
+// We try to avoid COPY relocations when possible.  A COPY relocation
+// may be required when an executable refers to a variable defined in
+// a shared library.  COPY relocations are problematic because they
+// tie the executable to the exact size of the variable in the shared
+// library.  We can avoid them if all the references to the variable
+// are in a writeable section.  In that case we can simply use dynamic
+// relocations.  However, when scanning relocs, we don't know when we
+// see the relocation whether we will be forced to use a COPY
+// relocation or not.  So we have to save the relocation during the
+// reloc scanning, and then emit it as a dynamic relocation if
+// necessary.  This class implements that.  It is used by the target
+// specific code.
+
+template<int size, bool big_endian>
+class Copy_relocs
+{
+ public:
+  Copy_relocs()
+    : entries_()
+  { }
 
   // Return whether we need a COPY reloc for a reloc against GSYM,
   // which is being applied to section SHNDX in OBJECT.
   static bool
   need_copy_reloc(const General_options*, Relobj* object, unsigned int shndx,
-                 Symbol* gsym);
+                 Sized_symbol<size>* gsym);
+
+  // Save a Rel against SYM for possible emission later.  SHNDX is the
+  // index of the section to which the reloc is being applied.
+  void
+  save(Symbol* sym, Relobj*, unsigned int shndx,
+       const elfcpp::Rel<size, big_endian>&);
+
+  // Save a Rela against SYM for possible emission later.
+  void
+  save(Symbol* sym, Relobj*, unsigned int shndx,
+       const elfcpp::Rela<size, big_endian>&);
+
+  // Return whether there are any relocs to emit.  This also discards
+  // entries which need not be emitted.
+  bool
+  any_to_emit();
+
+  // Emit relocs for each symbol which did not get a COPY reloc (i.e.,
+  // is still defined in the dynamic object).
+  template<int sh_type>
+  void
+  emit(Output_data_reloc<sh_type, true, size, big_endian>*);
+
+ private:
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
+  typedef typename elfcpp::Elf_types<size>::Elf_Addr Addend;
+
+  // This POD class holds the entries we are saving.
+  class Copy_reloc_entry
+  {
+   public:
+    Copy_reloc_entry(Symbol* sym, unsigned int reloc_type,
+                    Relobj* relobj, unsigned int shndx,
+                    Address address, Addend addend)
+      : sym_(sym), reloc_type_(reloc_type), relobj_(relobj),
+       shndx_(shndx), address_(address), addend_(addend)
+    { }
+
+    // Return whether we should emit this reloc.  If we should not
+    // emit, we clear it.
+    bool
+    should_emit();
+
+    // Emit this reloc.
+
+    void
+    emit(Output_data_reloc<elfcpp::SHT_REL, true, size, big_endian>*);
+
+    void
+    emit(Output_data_reloc<elfcpp::SHT_RELA, true, size, big_endian>*);
+
+   private:
+    Symbol* sym_;
+    unsigned int reloc_type_;
+    Relobj* relobj_;
+    unsigned int shndx_;
+    Address address_;
+    Addend addend_;
+  };
+
+  // A list of relocs to be saved.
+  typedef std::vector<Copy_reloc_entry> Copy_reloc_entries;
+
+  // The list of relocs we are saving.
+  Copy_reloc_entries entries_;
 };
 
 } // End namespace gold.
This page took 0.024377 seconds and 4 git commands to generate.