diff options
author | Ian Lance Taylor <iant@google.com> | 2007-10-16 00:42:36 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-10-16 00:42:36 +0000 |
commit | 1b64748beda63e896f48cb4c9409d8629db10747 (patch) | |
tree | 348cddbced43be8080c23530898a043cc7997dc9 | |
parent | a652a49c5f79172cefe59dfc895080e6df7e2dcf (diff) | |
download | gdb-1b64748beda63e896f48cb4c9409d8629db10747.zip gdb-1b64748beda63e896f48cb4c9409d8629db10747.tar.gz gdb-1b64748beda63e896f48cb4c9409d8629db10747.tar.bz2 |
From Craig Silverstein: support local GOT relocs for i386.
-rw-r--r-- | gold/i386.cc | 53 | ||||
-rw-r--r-- | gold/x86_64.cc | 1 |
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) { |