aboutsummaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-10-16 00:42:36 +0000
committerIan Lance Taylor <iant@google.com>2007-10-16 00:42:36 +0000
commit1b64748beda63e896f48cb4c9409d8629db10747 (patch)
tree348cddbced43be8080c23530898a043cc7997dc9 /gold
parenta652a49c5f79172cefe59dfc895080e6df7e2dcf (diff)
downloadfsf-binutils-gdb-1b64748beda63e896f48cb4c9409d8629db10747.zip
fsf-binutils-gdb-1b64748beda63e896f48cb4c9409d8629db10747.tar.gz
fsf-binutils-gdb-1b64748beda63e896f48cb4c9409d8629db10747.tar.bz2
From Craig Silverstein: support local GOT relocs for i386.
Diffstat (limited to 'gold')
-rw-r--r--gold/i386.cc53
-rw-r--r--gold/x86_64.cc1
2 files changed, 46 insertions, 8 deletions
diff --git a/gold/i386.cc b/gold/i386.cc
index 81d02b9..d82e50b 100644
--- a/gold/i386.cc
+++ b/gold/i386.cc
@@ -737,8 +737,8 @@ Target_i386::Scan::local(const General_options&,
Layout* layout,
Target_i386* target,
Sized_relobj<32, false>* object,
- unsigned int,
- const elfcpp::Rel<32, false>&,
+ unsigned int data_shndx,
+ const elfcpp::Rel<32, false>& reloc,
unsigned int r_type,
const elfcpp::Sym<32, false>&)
{
@@ -768,6 +768,25 @@ Target_i386::Scan::local(const General_options&,
target->got_section(symtab, layout);
break;
+ case elfcpp::R_386_GOT32:
+ {
+ // The symbol requires a GOT entry.
+ Output_data_got<32, false>* got = target->got_section(symtab, layout);
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
+ if (got->add_local(object, r_sym))
+ {
+ // If we are generating a shared object, we need to add a
+ // dynamic RELATIVE relocation for this symbol.
+ if (parameters->output_is_shared())
+ {
+ Reloc_section* rel_dyn = target->rel_dyn_section(layout);
+ rel_dyn->add_local(object, 0, elfcpp::R_386_RELATIVE,
+ data_shndx, reloc.get_r_offset());
+ }
+ }
+ }
+ break;
+
// These are relocations which should only be seen by the
// dynamic linker, and should never be seen here.
case elfcpp::R_386_COPY:
@@ -842,7 +861,6 @@ Target_i386::Scan::local(const General_options&,
}
break;
- case elfcpp::R_386_GOT32:
case elfcpp::R_386_PLT32:
case elfcpp::R_386_32PLT:
case elfcpp::R_386_TLS_GD_32:
@@ -1176,6 +1194,29 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
const Sized_relobj<32, false>* object = relinfo->object;
+ // Get the GOT offset if needed.
+ bool have_got_offset = false;
+ unsigned int got_offset = 0;
+ switch (r_type)
+ {
+ case elfcpp::R_386_GOT32:
+ if (gsym != NULL)
+ {
+ gold_assert(gsym->has_got_offset());
+ got_offset = gsym->got_offset();
+ }
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
+ got_offset = object->local_got_offset(r_sym);
+ }
+ have_got_offset = true;
+ break;
+
+ default:
+ break;
+ }
+
switch (r_type)
{
case elfcpp::R_386_NONE:
@@ -1214,10 +1255,8 @@ Target_i386::Relocate::relocate(const Relocate_info<32, false>* relinfo,
break;
case elfcpp::R_386_GOT32:
- // Local GOT offsets not yet supported.
- gold_assert(gsym);
- gold_assert(gsym->has_got_offset());
- Relocate_functions<32, false>::rel32(view, gsym->got_offset());
+ gold_assert(have_got_offset);
+ Relocate_functions<32, false>::rel32(view, got_offset);
break;
case elfcpp::R_386_GOTOFF:
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 34a53ac..75c2b7f 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -1181,7 +1181,6 @@ Target_x86_64::Relocate::relocate(const Relocate_info<64, false>* relinfo,
default:
break;
}
-
switch (r_type)
{