From 5a6f7e2db556f93765b75baf2d1ee1509225410d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 30 Nov 2006 23:52:50 +0000 Subject: Added a testsuite. More support for COPY relocations. --- gold/reloc.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 94 insertions(+), 1 deletion(-) (limited to 'gold/reloc.h') diff --git a/gold/reloc.h b/gold/reloc.h index 7829440..1edaa57 100644 --- a/gold/reloc.h +++ b/gold/reloc.h @@ -17,6 +17,12 @@ class Stringpool; class Symbol; class Layout; +template +class Sized_symbol; + +template +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 +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* 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&); + + // Save a Rela against SYM for possible emission later. + void + save(Symbol* sym, Relobj*, unsigned int shndx, + const elfcpp::Rela&); + + // 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 + void + emit(Output_data_reloc*); + + private: + typedef typename elfcpp::Elf_types::Elf_Addr Address; + typedef typename elfcpp::Elf_types::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*); + + void + emit(Output_data_reloc*); + + 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_entries; + + // The list of relocs we are saving. + Copy_reloc_entries entries_; }; } // End namespace gold. -- cgit v1.1