diff options
author | Ian Lance Taylor <iant@google.com> | 2006-12-01 16:51:25 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2006-12-01 16:51:25 +0000 |
commit | 16649710df23ad9038e0057035882a92e783f7e6 (patch) | |
tree | 7d4db6bb5578f6c90193108bc525a39f09ab379d /gold/i386.cc | |
parent | 8a82f7e3921015b4cbadf29379d8af9d9f6af891 (diff) | |
download | gdb-16649710df23ad9038e0057035882a92e783f7e6.zip gdb-16649710df23ad9038e0057035882a92e783f7e6.tar.gz gdb-16649710df23ad9038e0057035882a92e783f7e6.tar.bz2 |
Can now dynamically link hello, world.
Diffstat (limited to 'gold/i386.cc')
-rw-r--r-- | gold/i386.cc | 77 |
1 files changed, 69 insertions, 8 deletions
diff --git a/gold/i386.cc b/gold/i386.cc index 4cf90e9..ee3654c 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -51,7 +51,7 @@ class Target_i386 : public Sized_target<32, false> // Finalize the sections. void - do_finalize_sections(Layout*); + do_finalize_sections(const General_options*, Layout*); // Relocate a section. void @@ -231,7 +231,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, this->got_ = new Output_data_got<32, false>(options); layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, this->got_); + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->got_); // The old GNU linker creates a .got.plt section. We just // create another set of data in the .got section. Note that we @@ -239,7 +240,8 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, // might be empty. this->got_plt_ = new Output_data_space(4); layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, this->got_plt_); + elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, + this->got_plt_); // The first three entries are reserved. this->got_plt_->set_space_size(3 * 4); @@ -248,7 +250,7 @@ Target_i386::got_section(const General_options* options, Symbol_table* symtab, symtab->define_in_output_data(this, "_GLOBAL_OFFSET_TABLE_", this->got_plt_, 0, 0, elfcpp::STT_OBJECT, - elfcpp::STB_GLOBAL, + elfcpp::STB_LOCAL, elfcpp::STV_HIDDEN, 0, false, false); } @@ -284,6 +286,15 @@ class Output_data_plt_i386 : public Output_section_data void add_entry(Symbol* gsym); + // Return the .rel.plt section data. + const Reloc_section* + rel_plt() const + { return this->rel_; } + + protected: + void + do_adjust_output_section(Output_section* os); + private: // The size of an entry in the PLT. static const int plt_entry_size = 16; @@ -333,6 +344,16 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout, elfcpp::SHF_ALLOC, this->rel_); } +// For some reason + +void +Output_data_plt_i386::do_adjust_output_section(Output_section* os) +{ + // UnixWare sets the entsize of .plt to 4, and so does the old GNU + // linker, and so do we. + os->set_entsize(4); +} + // Add an entry to the PLT. void @@ -354,6 +375,7 @@ Output_data_plt_i386::add_entry(Symbol* gsym) this->got_plt_->set_space_size(got_offset + 4); // Every PLT entry needs a reloc. + gsym->set_needs_dynsym_entry(); this->rel_->add_global(gsym, elfcpp::R_386_JUMP_SLOT, this->got_plt_, got_offset); @@ -503,6 +525,10 @@ Target_i386::make_plt_entry(const General_options* options, this->plt_ = new Output_data_plt_i386(layout, this->got_plt_, options->is_shared()); + layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, + (elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR), + this->plt_); } this->plt_->add_entry(gsym); @@ -587,6 +613,7 @@ Target_i386::copy_reloc(const General_options* options, false, false); // Add the COPY reloc. + ssym->set_needs_dynsym_entry(); Reloc_section* rel_dyn = this->rel_dyn_section(layout); rel_dyn->add_global(ssym, elfcpp::R_386_COPY, dynbss, offset); } @@ -940,12 +967,46 @@ Target_i386::scan_relocs(const General_options& options, global_symbols); } -// Finalize the sections. This is where we emit any relocs we saved -// in an attempt to avoid generating extra COPY relocs. +// Finalize the sections. void -Target_i386::do_finalize_sections(Layout* layout) +Target_i386::do_finalize_sections(const General_options* options, + Layout* layout) { + // Fill in some more dynamic tags. + Output_data_dynamic* const odyn = layout->dynamic_data(); + if (odyn != NULL) + { + if (this->got_plt_ != NULL) + odyn->add_section_address(elfcpp::DT_PLTGOT, this->got_plt_); + + if (this->plt_ != NULL) + { + const Output_data* od = this->plt_->rel_plt(); + odyn->add_section_size(elfcpp::DT_PLTRELSZ, od); + odyn->add_section_address(elfcpp::DT_JMPREL, od); + odyn->add_constant(elfcpp::DT_PLTREL, elfcpp::DT_REL); + } + + if (this->rel_dyn_ != NULL) + { + const Output_data* od = this->rel_dyn_; + odyn->add_section_address(elfcpp::DT_REL, od); + odyn->add_section_size(elfcpp::DT_RELSZ, od); + odyn->add_constant(elfcpp::DT_RELENT, + elfcpp::Elf_sizes<32>::rel_size); + } + + if (!options->is_shared()) + { + // The value of the DT_DEBUG tag is filled in by the dynamic + // linker at run time, and used by the debugger. + odyn->add_constant(elfcpp::DT_DEBUG, 0); + } + } + + // Emit any relocs we saved in an attempt to avoid generating COPY + // relocs. if (this->copy_relocs_ == NULL) return; if (this->copy_relocs_->any_to_emit()) @@ -992,7 +1053,7 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo, if (gsym != NULL && gsym->is_defined_in_dynobj()) { if (gsym->has_plt_offset()) - address = target->plt_section()->address() + gsym->plt_offset(); + value = target->plt_section()->address() + gsym->plt_offset(); else gold_unreachable(); } |