diff options
author | Cary Coutant <ccoutant@google.com> | 2014-05-06 11:40:04 -0700 |
---|---|---|
committer | Cary Coutant <ccoutant@google.com> | 2014-05-06 14:29:42 -0700 |
commit | 57b2284c6318841612acef23c60fe7298a1ac91a (patch) | |
tree | 6038bb9bf0d79c984979e91f33191b0773979663 | |
parent | 757a636fb585824699b1cc4f8f23dbc3a6a6d914 (diff) | |
download | gdb-57b2284c6318841612acef23c60fe7298a1ac91a.zip gdb-57b2284c6318841612acef23c60fe7298a1ac91a.tar.gz gdb-57b2284c6318841612acef23c60fe7298a1ac91a.tar.bz2 |
Fix issue where first reserved word of GOT is not initialized if there
is no PLT.
gold/
PR gold/16900
* i386.cc (Output_data_got_plt_i386): New class.
(Output_data_plt_i386::Output_data_plt_i386): Change type of got_plt
parameter. Change all callers.
(Output_data_plt_i386::layout_): Remove.
(Output_data_plt_i386::got_plt_): Change type.
(Target_i386::got_plt_): Change type. Change all references.
(Target_i386::got_section): Create instance of new class.
(Output_data_got_plt_i386::do_write): New function.
* x86_64.cc (Output_data_got_plt_x86_64): New class.
(Output_data_plt_x86_64::Output_data_plt_x86_64): Change type of got_plt
parameter. Change all callers.
(Output_data_plt_x86_64::layout_): Remove.
(Output_data_plt_x86_64::got_plt_): Change type.
(Target_x86_64::got_plt_): Change type. Change all references.
(Target_x86_64::got_section): Create instance of new class.
(Output_data_got_plt_x86_64::do_write): New function.
(Output_data_plt_x86_64::do_write): Don't write reserved words in GOT.
(Target_x86_64<size>::init_got_plt_for_update): Create instance of new
class.
-rw-r--r-- | gold/ChangeLog | 23 | ||||
-rw-r--r-- | gold/i386.cc | 102 | ||||
-rw-r--r-- | gold/x86_64.cc | 110 |
3 files changed, 167 insertions, 68 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 52934f4..74a7512 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,26 @@ +2014-05-06 Cary Coutant <ccoutant@google.com> + + PR gold/16900 + * i386.cc (Output_data_got_plt_i386): New class. + (Output_data_plt_i386::Output_data_plt_i386): Change type of got_plt + parameter. Change all callers. + (Output_data_plt_i386::layout_): Remove. + (Output_data_plt_i386::got_plt_): Change type. + (Target_i386::got_plt_): Change type. Change all references. + (Target_i386::got_section): Create instance of new class. + (Output_data_got_plt_i386::do_write): New function. + * x86_64.cc (Output_data_got_plt_x86_64): New class. + (Output_data_plt_x86_64::Output_data_plt_x86_64): Change type of got_plt + parameter. Change all callers. + (Output_data_plt_x86_64::layout_): Remove. + (Output_data_plt_x86_64::got_plt_): Change type. + (Target_x86_64::got_plt_): Change type. Change all references. + (Target_x86_64::got_section): Create instance of new class. + (Output_data_got_plt_x86_64::do_write): New function. + (Output_data_plt_x86_64::do_write): Don't write reserved words in GOT. + (Target_x86_64<size>::init_got_plt_for_update): Create instance of new + class. + 2014-05-05 Cary Coutant <ccoutant@google.com> * gdb-index.cc (Gdb_index_info_reader): Don't complain about language diff --git a/gold/i386.cc b/gold/i386.cc index a2f7522..ed7f3f9 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -47,6 +47,32 @@ namespace using namespace gold; +// A class to handle the .got.plt section. + +class Output_data_got_plt_i386 : public Output_section_data_build +{ + public: + Output_data_got_plt_i386(Layout* layout) + : Output_section_data_build(4), + layout_(layout) + { } + + protected: + // Write out the PLT data. + void + do_write(Output_file*); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, "** GOT PLT"); } + + private: + // A pointer to the Layout class, so that we can find the .dynamic + // section when we write out the GOT PLT section. + Layout* layout_; +}; + // A class to handle the PLT data. // This is an abstract base class that handles most of the linker details // but does not know the actual contents of PLT entries. The derived @@ -58,7 +84,7 @@ class Output_data_plt_i386 : public Output_section_data typedef Output_data_reloc<elfcpp::SHT_REL, true, 32, false> Reloc_section; Output_data_plt_i386(Layout*, uint64_t addralign, - Output_data_space*, Output_data_space*); + Output_data_got_plt_i386*, Output_data_space*); // Add an entry to the PLT. void @@ -201,9 +227,6 @@ class Output_data_plt_i386 : public Output_section_data unsigned int got_offset; }; - // A pointer to the Layout class, so that we can find the .dynamic - // section when we write out the GOT PLT section. - Layout* layout_; // The reloc section. Reloc_section* rel_; // The TLS_DESC relocations, if necessary. These must follow the @@ -213,7 +236,7 @@ class Output_data_plt_i386 : public Output_section_data // regular relocatoins and the TLS_DESC relocations. Reloc_section* irelative_rel_; // The .got.plt section. - Output_data_space* got_plt_; + Output_data_got_plt_i386* got_plt_; // The part of the .got.plt section used for IRELATIVE relocs. Output_data_space* got_irelative_; // The number of PLT entries. @@ -236,7 +259,7 @@ class Output_data_plt_i386_standard : public Output_data_plt_i386 { public: Output_data_plt_i386_standard(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative) { } @@ -267,7 +290,7 @@ class Output_data_plt_i386_exec : public Output_data_plt_i386_standard { public: Output_data_plt_i386_exec(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386_standard(layout, got_plt, got_irelative) { } @@ -298,7 +321,7 @@ class Output_data_plt_i386_dyn : public Output_data_plt_i386_standard { public: Output_data_plt_i386_dyn(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386_standard(layout, got_plt, got_irelative) { } @@ -506,14 +529,14 @@ class Target_i386 : public Sized_target<32, false> // This chooses the right PLT flavor for an executable or a shared object. Output_data_plt_i386* make_data_plt(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative, bool dyn) { return this->do_make_data_plt(layout, got_plt, got_irelative, dyn); } virtual Output_data_plt_i386* do_make_data_plt(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative, bool dyn) { @@ -720,7 +743,7 @@ class Target_i386 : public Sized_target<32, false> got_section(Symbol_table*, Layout*); // Get the GOT PLT section. - Output_data_space* + Output_data_got_plt_i386* got_plt_section() const { gold_assert(this->got_plt_ != NULL); @@ -813,7 +836,7 @@ class Target_i386 : public Sized_target<32, false> // The PLT section. Output_data_plt_i386* plt_; // The GOT PLT section. - Output_data_space* got_plt_; + Output_data_got_plt_i386* got_plt_; // The GOT section for IRELATIVE relocations. Output_data_space* got_irelative_; // The GOT section for TLSDESC relocations. @@ -885,7 +908,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) | elfcpp::SHF_WRITE), this->got_, got_order, true); - this->got_plt_ = new Output_data_space(4, "** GOT PLT"); + this->got_plt_ = new Output_data_got_plt_i386(layout); layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), @@ -972,18 +995,39 @@ Target_i386::rel_irelative_section(Layout* layout) return this->rel_irelative_; } +// Write the first three reserved words of the .got.plt section. +// The remainder of the section is written while writing the PLT +// in Output_data_plt_i386::do_write. + +void +Output_data_got_plt_i386::do_write(Output_file* of) +{ + // The first entry in the GOT is the address of the .dynamic section + // aka the PT_DYNAMIC segment. The next two entries are reserved. + // We saved space for them when we created the section in + // Target_i386::got_section. + const off_t got_file_offset = this->offset(); + gold_assert(this->data_size() >= 12); + unsigned char* const got_view = of->get_output_view(got_file_offset, 12); + Output_section* dynamic = this->layout_->dynamic_section(); + uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address(); + elfcpp::Swap<32, false>::writeval(got_view, dynamic_addr); + memset(got_view + 4, 0, 8); + of->write_output_view(got_file_offset, 12, got_view); +} + // Create the PLT section. The ordinary .got section is an argument, // since we need to refer to the start. We also create our own .got // section just for PLT entries. Output_data_plt_i386::Output_data_plt_i386(Layout* layout, uint64_t addralign, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_section_data(addralign), - layout_(layout), tls_desc_rel_(NULL), - irelative_rel_(NULL), got_plt_(got_plt), got_irelative_(got_irelative), - count_(0), irelative_count_(0), global_ifuncs_(), local_ifuncs_() + tls_desc_rel_(NULL), irelative_rel_(NULL), got_plt_(got_plt), + got_irelative_(got_irelative), count_(0), irelative_count_(0), + global_ifuncs_(), local_ifuncs_() { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, @@ -1323,6 +1367,7 @@ Output_data_plt_i386::do_write(Output_file* of) const section_size_type got_size = convert_to_section_size_type(this->got_plt_->data_size() + this->got_irelative_->data_size()); + unsigned char* const got_view = of->get_output_view(got_file_offset, got_size); @@ -1334,18 +1379,9 @@ Output_data_plt_i386::do_write(Output_file* of) this->fill_first_plt_entry(pov, got_address); pov += this->get_plt_entry_size(); - unsigned char* got_pov = got_view; - - // The first entry in the GOT is the address of the .dynamic section - // aka the PT_DYNAMIC segment. The next two entries are reserved. - // We saved space for them when we created the section in - // Target_i386::got_section. - Output_section* dynamic = this->layout_->dynamic_section(); - uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address(); - elfcpp::Swap<32, false>::writeval(got_pov, dynamic_addr); - got_pov += 4; - memset(got_pov, 0, 8); - got_pov += 8; + // The first three entries in the GOT are reserved, and are written + // by Output_data_got_plt_i386::do_write. + unsigned char* got_pov = got_view + 12; const int rel_size = elfcpp::Elf_sizes<32>::rel_size; @@ -3834,7 +3870,7 @@ class Output_data_plt_i386_nacl : public Output_data_plt_i386 { public: Output_data_plt_i386_nacl(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386(layout, plt_entry_size, got_plt, got_irelative) { } @@ -3863,7 +3899,7 @@ class Output_data_plt_i386_nacl_exec : public Output_data_plt_i386_nacl { public: Output_data_plt_i386_nacl_exec(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386_nacl(layout, got_plt, got_irelative) { } @@ -3892,7 +3928,7 @@ class Output_data_plt_i386_nacl_dyn : public Output_data_plt_i386_nacl { public: Output_data_plt_i386_nacl_dyn(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative) : Output_data_plt_i386_nacl(layout, got_plt, got_irelative) { } @@ -3926,7 +3962,7 @@ class Target_i386_nacl : public Target_i386 protected: virtual Output_data_plt_i386* do_make_data_plt(Layout* layout, - Output_data_space* got_plt, + Output_data_got_plt_i386* got_plt, Output_data_space* got_irelative, bool dyn) { diff --git a/gold/x86_64.cc b/gold/x86_64.cc index aa9e5b4..255ebb9 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -48,6 +48,37 @@ namespace using namespace gold; +// A class to handle the .got.plt section. + +class Output_data_got_plt_x86_64 : public Output_section_data_build +{ + public: + Output_data_got_plt_x86_64(Layout* layout) + : Output_section_data_build(8), + layout_(layout) + { } + + Output_data_got_plt_x86_64(Layout* layout, off_t data_size) + : Output_section_data_build(data_size, 8), + layout_(layout) + { } + + protected: + // Write out the PLT data. + void + do_write(Output_file*); + + // Write to a map file. + void + do_print_to_mapfile(Mapfile* mapfile) const + { mapfile->print_output_data(this, "** GOT PLT"); } + + private: + // A pointer to the Layout class, so that we can find the .dynamic + // section when we write out the GOT PLT section. + Layout* layout_; +}; + // A class to handle the PLT data. // This is an abstract base class that handles most of the linker details // but does not know the actual contents of PLT entries. The derived @@ -61,9 +92,9 @@ class Output_data_plt_x86_64 : public Output_section_data Output_data_plt_x86_64(Layout* layout, uint64_t addralign, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) - : Output_section_data(addralign), layout_(layout), tlsdesc_rel_(NULL), + : Output_section_data(addralign), tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got), got_plt_(got_plt), got_irelative_(got_irelative), count_(0), irelative_count_(0), tlsdesc_got_offset_(-1U), free_list_() @@ -71,12 +102,12 @@ class Output_data_plt_x86_64 : public Output_section_data Output_data_plt_x86_64(Layout* layout, uint64_t plt_entry_size, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) : Output_section_data((plt_count + 1) * plt_entry_size, plt_entry_size, false), - layout_(layout), tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got), + tlsdesc_rel_(NULL), irelative_rel_(NULL), got_(got), got_plt_(got_plt), got_irelative_(got_irelative), count_(plt_count), irelative_count_(0), tlsdesc_got_offset_(-1U), free_list_() { @@ -268,9 +299,6 @@ class Output_data_plt_x86_64 : public Output_section_data void do_write(Output_file*); - // A pointer to the Layout class, so that we can find the .dynamic - // section when we write out the GOT PLT section. - Layout* layout_; // The reloc section. Reloc_section* rel_; // The TLSDESC relocs, if necessary. These must follow the regular @@ -282,7 +310,7 @@ class Output_data_plt_x86_64 : public Output_section_data // The .got section. Output_data_got<64, false>* got_; // The .got.plt section. - Output_data_space* got_plt_; + Output_data_got_plt_x86_64* got_plt_; // The part of the .got.plt section used for IRELATIVE relocs. Output_data_space* got_irelative_; // The number of PLT entries. @@ -303,7 +331,7 @@ class Output_data_plt_x86_64_standard : public Output_data_plt_x86_64<size> public: Output_data_plt_x86_64_standard(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) : Output_data_plt_x86_64<size>(layout, plt_entry_size, got, got_plt, got_irelative) @@ -311,7 +339,7 @@ class Output_data_plt_x86_64_standard : public Output_data_plt_x86_64<size> Output_data_plt_x86_64_standard(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) : Output_data_plt_x86_64<size>(layout, plt_entry_size, @@ -618,7 +646,7 @@ class Target_x86_64 : public Sized_target<size, false> Output_data_plt_x86_64<size>* make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) { return this->do_make_data_plt(layout, got, got_plt, got_irelative); @@ -627,7 +655,7 @@ class Target_x86_64 : public Sized_target<size, false> Output_data_plt_x86_64<size>* make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) { @@ -638,7 +666,7 @@ class Target_x86_64 : public Sized_target<size, false> virtual Output_data_plt_x86_64<size>* do_make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) { return new Output_data_plt_x86_64_standard<size>(layout, got, got_plt, @@ -648,7 +676,7 @@ class Target_x86_64 : public Sized_target<size, false> virtual Output_data_plt_x86_64<size>* do_make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) { @@ -847,7 +875,7 @@ class Target_x86_64 : public Sized_target<size, false> got_section(Symbol_table*, Layout*); // Get the GOT PLT section. - Output_data_space* + Output_data_got_plt_x86_64* got_plt_section() const { gold_assert(this->got_plt_ != NULL); @@ -958,7 +986,7 @@ class Target_x86_64 : public Sized_target<size, false> // The PLT section. Output_data_plt_x86_64<size>* plt_; // The GOT PLT section. - Output_data_space* got_plt_; + Output_data_got_plt_x86_64* got_plt_; // The GOT section for IRELATIVE relocations. Output_data_space* got_irelative_; // The GOT section for TLSDESC relocations. @@ -1074,7 +1102,7 @@ Target_x86_64<size>::got_section(Symbol_table* symtab, Layout* layout) | elfcpp::SHF_WRITE), this->got_, got_order, true); - this->got_plt_ = new Output_data_space(8, "** GOT PLT"); + this->got_plt_ = new Output_data_got_plt_x86_64(layout); layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), @@ -1163,6 +1191,27 @@ Target_x86_64<size>::rela_irelative_section(Layout* layout) return this->rela_irelative_; } +// Write the first three reserved words of the .got.plt section. +// The remainder of the section is written while writing the PLT +// in Output_data_plt_i386::do_write. + +void +Output_data_got_plt_x86_64::do_write(Output_file* of) +{ + // The first entry in the GOT is the address of the .dynamic section + // aka the PT_DYNAMIC segment. The next two entries are reserved. + // We saved space for them when we created the section in + // Target_x86_64::got_section. + const off_t got_file_offset = this->offset(); + gold_assert(this->data_size() >= 24); + unsigned char* const got_view = of->get_output_view(got_file_offset, 24); + Output_section* dynamic = this->layout_->dynamic_section(); + uint64_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address(); + elfcpp::Swap<64, false>::writeval(got_view, dynamic_addr); + memset(got_view + 8, 0, 16); + of->write_output_view(got_file_offset, 24, got_view); +} + // Initialize the PLT section. template<int size> @@ -1198,7 +1247,7 @@ Output_data_plt_x86_64<size>::add_entry(Symbol_table* symtab, Layout* layout, unsigned int* pcount; unsigned int offset; unsigned int reserved; - Output_data_space* got; + Output_section_data_build* got; if (gsym->type() == elfcpp::STT_GNU_IFUNC && gsym->can_use_relative_reloc(false)) { @@ -1605,18 +1654,9 @@ Output_data_plt_x86_64<size>::do_write(Output_file* of) this->fill_first_plt_entry(pov, got_address, plt_address); pov += this->get_plt_entry_size(); - unsigned char* got_pov = got_view; - - // The first entry in the GOT is the address of the .dynamic section - // aka the PT_DYNAMIC segment. The next two entries are reserved. - // We saved space for them when we created the section in - // Target_x86_64::got_section. - Output_section* dynamic = this->layout_->dynamic_section(); - uint32_t dynamic_addr = dynamic == NULL ? 0 : dynamic->address(); - elfcpp::Swap<64, false>::writeval(got_pov, dynamic_addr); - got_pov += 8; - memset(got_pov, 0, 16); - got_pov += 16; + // The first three entries in the GOT are reserved, and are written + // by Output_data_got_plt_x86_64::do_write. + unsigned char* got_pov = got_view + 24; unsigned int plt_offset = this->get_plt_entry_size(); unsigned int got_offset = 24; @@ -1777,7 +1817,7 @@ Target_x86_64<size>::init_got_plt_for_update(Symbol_table* symtab, true); // Add the three reserved entries. - this->got_plt_ = new Output_data_space((plt_count + 3) * 8, 8, "** GOT PLT"); + this->got_plt_ = new Output_data_got_plt_x86_64(layout, (plt_count + 3) * 8); layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), @@ -4500,7 +4540,7 @@ class Output_data_plt_x86_64_nacl : public Output_data_plt_x86_64<size> public: Output_data_plt_x86_64_nacl(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) : Output_data_plt_x86_64<size>(layout, plt_entry_size, got, got_plt, got_irelative) @@ -4508,7 +4548,7 @@ class Output_data_plt_x86_64_nacl : public Output_data_plt_x86_64<size> Output_data_plt_x86_64_nacl(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) : Output_data_plt_x86_64<size>(layout, plt_entry_size, @@ -4581,7 +4621,7 @@ class Target_x86_64_nacl : public Target_x86_64<size> virtual Output_data_plt_x86_64<size>* do_make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative) { return new Output_data_plt_x86_64_nacl<size>(layout, got, got_plt, @@ -4591,7 +4631,7 @@ class Target_x86_64_nacl : public Target_x86_64<size> virtual Output_data_plt_x86_64<size>* do_make_data_plt(Layout* layout, Output_data_got<64, false>* got, - Output_data_space* got_plt, + Output_data_got_plt_x86_64* got_plt, Output_data_space* got_irelative, unsigned int plt_count) { |