diff options
author | Ian Lance Taylor <iant@google.com> | 2007-10-30 01:21:51 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-10-30 01:21:51 +0000 |
commit | ee9e9e864486f29b33d7533d81dd0ab852a92a7d (patch) | |
tree | f6ca3010347effc2f91a5527e1cb8fc71f78ec45 /gold | |
parent | 87aa5fb9f31750b219ab8dacc10a138d1ce09d49 (diff) | |
download | gdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.zip gdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.tar.gz gdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.tar.bz2 |
From Craig Silverstein: Implement GOTPLT64 and PLTOFF64.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/x86_64.cc | 33 |
1 files changed, 29 insertions, 4 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 3f25bbf..158090c 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -289,7 +289,6 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) // create another set of data in the .got section. Note that we // always create a PLT if we create a GOT, although the PLT // might be empty. - // TODO(csilvers): do we really need an alignment of 8? this->got_plt_ = new Output_data_space(8); layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, @@ -382,7 +381,6 @@ class Output_data_plt_x86_64 : public Output_section_data Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, Output_data_space* got_plt) - // TODO(csilvers): do we really need an alignment of 8? : Output_section_data(8), got_plt_(got_plt), count_(0) { this->rel_ = new Reloc_section(); @@ -743,12 +741,15 @@ Target_x86_64::Scan::local(const General_options&, case elfcpp::R_X86_64_PLTOFF64: // We need a GOT section. target->got_section(symtab, layout); + // For PLTOFF64, we'd normally want a PLT section, but since we + // know this is a local symbol, no PLT is needed. break; case elfcpp::R_X86_64_GOT64: case elfcpp::R_X86_64_GOT32: case elfcpp::R_X86_64_GOTPCREL64: case elfcpp::R_X86_64_GOTPCREL: + case elfcpp::R_X86_64_GOTPLT64: { // The symbol requires a GOT entry. Output_data_got<64, false>* got = target->got_section(symtab, layout); @@ -764,6 +765,8 @@ Target_x86_64::Scan::local(const General_options&, data_shndx, reloc.get_r_offset(), 0); } } + // For GOTPLT64, we'd normally want a PLT section, but since + // we know this is a local symbol, no PLT is needed. } break; @@ -831,7 +834,6 @@ Target_x86_64::Scan::local(const General_options&, } break; - case elfcpp::R_X86_64_GOTPLT64: case elfcpp::R_X86_64_SIZE32: case elfcpp::R_X86_64_SIZE64: default: @@ -933,6 +935,11 @@ Target_x86_64::Scan::global(const General_options& options, gsym->got_offset(), 0); } } + // For GOTPLT64, we also need a PLT entry (but only if the + // symbol is not fully resolved). + if (r_type == elfcpp::R_X86_64_GOTPLT64 + && !gsym->final_value_is_known()) + target->make_plt_entry(symtab, layout, gsym); } break; @@ -950,6 +957,11 @@ Target_x86_64::Scan::global(const General_options& options, case elfcpp::R_X86_64_PLTOFF64: // We need a GOT section. target->got_section(symtab, layout); + // For PLTOFF64, we also need a PLT entry (but only if the + // symbol is not fully resolved). + if (r_type == elfcpp::R_X86_64_PLTOFF64 + && !gsym->final_value_is_known()) + target->make_plt_entry(symtab, layout, gsym); break; case elfcpp::R_X86_64_COPY: @@ -1239,10 +1251,24 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, gold_assert(gsym == NULL || gsym->has_plt_offset() || gsym->final_value_is_known()); + // Note: while this code looks the same as for R_X86_64_PC32, it + // behaves differently because psymval was set to point to + // the PLT entry, rather than the symbol, in Scan::global(). Relocate_functions<64, false>::pcrela32(view, object, psymval, addend, address); break; + case elfcpp::R_X86_64_PLTOFF64: + { + gold_assert(gsym); + gold_assert(gsym->has_plt_offset() + || gsym->final_value_is_known()); + elfcpp::Elf_types<64>::Elf_Addr got_address; + got_address = target->got_section(NULL, NULL)->address(); + Relocate_functions<64, false>::pcrela64(view, object, psymval, addend, + - got_address); + } + case elfcpp::R_X86_64_GOT32: gold_assert(have_got_offset); Relocate_functions<64, false>::rela32(view, got_offset, addend); @@ -1329,7 +1355,6 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo, case elfcpp::R_X86_64_SIZE32: case elfcpp::R_X86_64_SIZE64: - case elfcpp::R_X86_64_PLTOFF64: // FIXME: implement me! default: gold_error_at_location(relinfo, relnum, rela.get_r_offset(), _("unsupported reloc %u"), |