aboutsummaryrefslogtreecommitdiff
path: root/gold/x86_64.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-30 01:21:51 +0000
committerIan Lance Taylor <iant@google.com>2007-10-30 01:21:51 +0000
commitee9e9e864486f29b33d7533d81dd0ab852a92a7d (patch)
treef6ca3010347effc2f91a5527e1cb8fc71f78ec45 /gold/x86_64.cc
parent87aa5fb9f31750b219ab8dacc10a138d1ce09d49 (diff)
downloadgdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.zip
gdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.tar.gz
gdb-ee9e9e864486f29b33d7533d81dd0ab852a92a7d.tar.bz2
From Craig Silverstein: Implement GOTPLT64 and PLTOFF64.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r--gold/x86_64.cc33
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"),