diff options
Diffstat (limited to 'gold/reloc.h')
-rw-r--r-- | gold/reloc.h | 95 |
1 files changed, 94 insertions, 1 deletions
diff --git a/gold/reloc.h b/gold/reloc.h index 7829440bf49..1edaa579cee 100644 --- a/gold/reloc.h +++ b/gold/reloc.h @@ -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. |