X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Freloc.h;h=39ffe4ac229eef971dc8c780d4becd899cc11147;hb=780b23606d1373bf8d28535bbf6b3f87af863bde;hp=cc1149b6bc1e6f85792f4a8dadeb92fd214839d0;hpb=6cb15b7f89d59fb61780b01ad3de2340f33c3728;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/reloc.h b/gold/reloc.h index cc1149b6bc..39ffe4ac22 100644 --- a/gold/reloc.h +++ b/gold/reloc.h @@ -23,18 +23,22 @@ #ifndef GOLD_RELOC_H #define GOLD_RELOC_H +#include #include +#include "elfcpp.h" #include "workqueue.h" namespace gold { class General_options; +class Object; class Relobj; class Read_relocs_data; class Symbol; class Layout; +class Output_section; template class Sized_symbol; @@ -66,15 +70,18 @@ class Read_relocs : public Task // The standard Task methods. - Is_runnable_type - is_runnable(Workqueue*); + Task_token* + is_runnable(); - Task_locker* - locks(Workqueue*); + void + locks(Task_locker*); void run(Workqueue*); + std::string + get_name() const; + private: const General_options& options_; Symbol_table* symtab_; @@ -101,18 +108,19 @@ class Scan_relocs : public Task // The standard Task methods. - Is_runnable_type - is_runnable(Workqueue*); + Task_token* + is_runnable(); - Task_locker* - locks(Workqueue*); + void + locks(Task_locker*); void run(Workqueue*); - private: - class Scan_relocs_locker; + std::string + get_name() const; + private: const General_options& options_; Symbol_table* symtab_; Layout* layout_; @@ -129,30 +137,36 @@ class Relocate_task : public Task public: Relocate_task(const General_options& options, const Symbol_table* symtab, const Layout* layout, Relobj* object, Output_file* of, - Task_token* final_blocker) + Task_token* input_sections_blocker, + Task_token* output_sections_blocker, Task_token* final_blocker) : options_(options), symtab_(symtab), layout_(layout), object_(object), - of_(of), final_blocker_(final_blocker) + of_(of), input_sections_blocker_(input_sections_blocker), + output_sections_blocker_(output_sections_blocker), + final_blocker_(final_blocker) { } // The standard Task methods. - Is_runnable_type - is_runnable(Workqueue*); + Task_token* + is_runnable(); - Task_locker* - locks(Workqueue*); + void + locks(Task_locker*); void run(Workqueue*); - private: - class Relocate_locker; + std::string + get_name() const; + private: const General_options& options_; const Symbol_table* symtab_; const Layout* layout_; Relobj* object_; Output_file* of_; + Task_token* input_sections_blocker_; + Task_token* output_sections_blocker_; Task_token* final_blocker_; }; @@ -192,6 +206,34 @@ private: elfcpp::Swap::writeval(wv, x); } + // Do a simple relocation with the addend in the relocation. + // VALSIZE is the size of the value. + template + static inline void + rela(unsigned char* view, + typename elfcpp::Swap::Valtype value, + typename elfcpp::Swap::Valtype addend) + { + typedef typename elfcpp::Swap::Valtype Valtype; + Valtype* wv = reinterpret_cast(view); + elfcpp::Swap::writeval(wv, value + addend); + } + + // Do a simple relocation using a symbol value with the addend in + // the relocation. VALSIZE is the size of the value. + template + static inline void + rela(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + typename elfcpp::Swap::Valtype addend) + { + typedef typename elfcpp::Swap::Valtype Valtype; + Valtype* wv = reinterpret_cast(view); + Valtype x = psymval->value(object, addend); + elfcpp::Swap::writeval(wv, x); + } + // Do a simple PC relative relocation with the addend in the section // contents. VALSIZE is the size of the value. template @@ -223,6 +265,36 @@ private: elfcpp::Swap::writeval(wv, x - address); } + // Do a simple PC relative relocation with the addend in the + // relocation. VALSIZE is the size of the value. + template + static inline void + pcrela(unsigned char* view, + typename elfcpp::Swap::Valtype value, + typename elfcpp::Swap::Valtype addend, + typename elfcpp::Elf_types::Elf_Addr address) + { + typedef typename elfcpp::Swap::Valtype Valtype; + Valtype* wv = reinterpret_cast(view); + elfcpp::Swap::writeval(wv, value + addend - address); + } + + // Do a simple PC relative relocation with a Symbol_value with the + // addend in the relocation. VALSIZE is the size of the value. + template + static inline void + pcrela(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + typename elfcpp::Swap::Valtype addend, + typename elfcpp::Elf_types::Elf_Addr address) + { + typedef typename elfcpp::Swap::Valtype Valtype; + Valtype* wv = reinterpret_cast(view); + Valtype x = psymval->value(object, addend); + elfcpp::Swap::writeval(wv, x - address); + } + typedef Relocate_functions This; public: @@ -238,6 +310,18 @@ public: const Symbol_value* psymval) { This::template rel<8>(view, object, psymval); } + // Do an 8-bit RELA relocation with the addend in the relocation. + static inline void + rela8(unsigned char* view, unsigned char value, unsigned char addend) + { This::template rela<8>(view, value, addend); } + + static inline void + rela8(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + unsigned char addend) + { This::template rela<8>(view, object, psymval, addend); } + // Do a simple 8-bit PC relative relocation with the addend in the // section contents. static inline void @@ -252,6 +336,21 @@ public: typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<8>(view, object, psymval, address); } + // Do a simple 8-bit PC relative RELA relocation with the addend in + // the reloc. + static inline void + pcrela8(unsigned char* view, unsigned char value, unsigned char addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<8>(view, value, addend, address); } + + static inline void + pcrela8(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + unsigned char addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<8>(view, object, psymval, addend, address); } + // Do a simple 16-bit REL relocation with the addend in the section // contents. static inline void @@ -264,10 +363,22 @@ public: const Symbol_value* psymval) { This::template rel<16>(view, object, psymval); } - // Do a simple 32-bit PC relative REL relocation with the addend in + // Do an 16-bit RELA relocation with the addend in the relocation. + static inline void + rela16(unsigned char* view, elfcpp::Elf_Half value, elfcpp::Elf_Half addend) + { This::template rela<16>(view, value, addend); } + + static inline void + rela16(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Half addend) + { This::template rela<16>(view, object, psymval, addend); } + + // Do a simple 16-bit PC relative REL relocation with the addend in // the section contents. static inline void - pcrel16(unsigned char* view, elfcpp::Elf_Word value, + pcrel16(unsigned char* view, elfcpp::Elf_Half value, typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<16>(view, value, address); } @@ -278,6 +389,22 @@ public: typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<16>(view, object, psymval, address); } + // Do a simple 16-bit PC relative RELA relocation with the addend in + // the reloc. + static inline void + pcrela16(unsigned char* view, elfcpp::Elf_Half value, + elfcpp::Elf_Half addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<16>(view, value, addend, address); } + + static inline void + pcrela16(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Half addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<16>(view, object, psymval, addend, address); } + // Do a simple 32-bit REL relocation with the addend in the section // contents. static inline void @@ -290,6 +417,18 @@ public: const Symbol_value* psymval) { This::template rel<32>(view, object, psymval); } + // Do an 32-bit RELA relocation with the addend in the relocation. + static inline void + rela32(unsigned char* view, elfcpp::Elf_Word value, elfcpp::Elf_Word addend) + { This::template rela<32>(view, value, addend); } + + static inline void + rela32(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Word addend) + { This::template rela<32>(view, object, psymval, addend); } + // Do a simple 32-bit PC relative REL relocation with the addend in // the section contents. static inline void @@ -304,6 +443,22 @@ public: typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<32>(view, object, psymval, address); } + // Do a simple 32-bit PC relative RELA relocation with the addend in + // the relocation. + static inline void + pcrela32(unsigned char* view, elfcpp::Elf_Word value, + elfcpp::Elf_Word addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<32>(view, value, addend, address); } + + static inline void + pcrela32(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Word addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<32>(view, object, psymval, addend, address); } + // Do a simple 64-bit REL relocation with the addend in the section // contents. static inline void @@ -316,6 +471,19 @@ public: const Symbol_value* psymval) { This::template rel<64>(view, object, psymval); } + // Do a 64-bit RELA relocation with the addend in the relocation. + static inline void + rela64(unsigned char* view, elfcpp::Elf_Xword value, + elfcpp::Elf_Xword addend) + { This::template rela<64>(view, value, addend); } + + static inline void + rela64(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Xword addend) + { This::template rela<64>(view, object, psymval, addend); } + // Do a simple 64-bit PC relative REL relocation with the addend in // the section contents. static inline void @@ -329,6 +497,22 @@ public: const Symbol_value* psymval, typename elfcpp::Elf_types::Elf_Addr address) { This::template pcrel<64>(view, object, psymval, address); } + + // Do a simple 64-bit PC relative RELA relocation with the addend in + // the relocation. + static inline void + pcrela64(unsigned char* view, elfcpp::Elf_Xword value, + elfcpp::Elf_Xword addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<64>(view, value, addend, address); } + + static inline void + pcrela64(unsigned char* view, + const Sized_relobj* object, + const Symbol_value* psymval, + elfcpp::Elf_Xword addend, + typename elfcpp::Elf_types::Elf_Addr address) + { This::template pcrela<64>(view, object, psymval, addend, address); } }; // We try to avoid COPY relocations when possible. A COPY relocation @@ -362,12 +546,12 @@ class Copy_relocs // index of the section to which the reloc is being applied. void save(Symbol* sym, Relobj*, unsigned int shndx, - const elfcpp::Rel&); + Output_section* output_section, const elfcpp::Rel&); // Save a Rela against SYM for possible emission later. void save(Symbol* sym, Relobj*, unsigned int shndx, - const elfcpp::Rela&); + Output_section* output_section, const elfcpp::Rela&); // Return whether there are any relocs to emit. This also discards // entries which need not be emitted. @@ -390,9 +574,11 @@ class Copy_relocs public: Copy_reloc_entry(Symbol* sym, unsigned int reloc_type, Relobj* relobj, unsigned int shndx, + Output_section* output_section, Address address, Addend addend) : sym_(sym), reloc_type_(reloc_type), relobj_(relobj), - shndx_(shndx), address_(address), addend_(addend) + shndx_(shndx), output_section_(output_section), + address_(address), addend_(addend) { } // Return whether we should emit this reloc. If we should not @@ -413,6 +599,7 @@ class Copy_relocs unsigned int reloc_type_; Relobj* relobj_; unsigned int shndx_; + Output_section* output_section_; Address address_; Addend addend_; }; @@ -424,6 +611,53 @@ class Copy_relocs Copy_reloc_entries entries_; }; +// Track relocations while reading a section. This lets you ask for +// the relocation at a certain offset, and see how relocs occur +// between points of interest. + +template +class Track_relocs +{ + public: + Track_relocs() + : prelocs_(NULL), len_(0), pos_(0), reloc_size_(0) + { } + + // Initialize the Track_relocs object. OBJECT is the object holding + // the reloc section, RELOC_SHNDX is the section index of the reloc + // section, and RELOC_TYPE is the type of the reloc section + // (elfcpp::SHT_REL or elfcpp::SHT_RELA). This returns false if + // something went wrong. + bool + initialize(Object* object, unsigned int reloc_shndx, + unsigned int reloc_type); + + // Return the offset in the data section to which the next reloc + // applies. THis returns -1 if there is no next reloc. + off_t + next_offset() const; + + // Return the symbol index of the next reloc. This returns -1U if + // there is no next reloc. + unsigned int + next_symndx() const; + + // Advance to OFFSET within the data section, and return the number + // of relocs which would be skipped. + int + advance(off_t offset); + + private: + // The contents of the input object's reloc section. + const unsigned char* prelocs_; + // The length of the reloc section. + section_size_type len_; + // Our current position in the reloc section. + section_size_type pos_; + // The size of the relocs in the section. + int reloc_size_; +}; + } // End namespace gold. #endif // !defined(GOLD_RELOC_H)