aboutsummaryrefslogtreecommitdiff
path: root/gold/x86_64.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-11-02 04:08:52 +0000
committerIan Lance Taylor <iant@google.com>2007-11-02 04:08:52 +0000
commit86849f1facff8e5639c539a6e455575f25649028 (patch)
treee914f61eb7f0245374ee8aaede2a63dddddb16cc /gold/x86_64.cc
parentfe906b004d1558c79aee1d74f063b7d2cf8d08f5 (diff)
downloadgdb-86849f1facff8e5639c539a6e455575f25649028.zip
gdb-86849f1facff8e5639c539a6e455575f25649028.tar.gz
gdb-86849f1facff8e5639c539a6e455575f25649028.tar.bz2
From Cary Coutant: Correct generation of RELATIVE relocs.
Diffstat (limited to 'gold/x86_64.cc')
-rw-r--r--gold/x86_64.cc41
1 files changed, 28 insertions, 13 deletions
diff --git a/gold/x86_64.cc b/gold/x86_64.cc
index 5597d59..223523e 100644
--- a/gold/x86_64.cc
+++ b/gold/x86_64.cc
@@ -743,12 +743,17 @@ Target_x86_64::Scan::local(const General_options&,
// relocate it easily.
if (parameters->output_is_position_independent())
{
- // FIXME: R_X86_64_RELATIVE assumes a 64-bit relocation.
- gold_assert(r_type == elfcpp::R_X86_64_64);
-
Reloc_section* rela_dyn = target->rela_dyn_section(layout);
- rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
- data_shndx, reloc.get_r_offset(), 0);
+ if (r_type == elfcpp::R_X86_64_64)
+ rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
+ data_shndx, reloc.get_r_offset(), 0);
+ else
+ {
+ unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
+ rela_dyn->add_local(object, r_sym, r_type, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend());
+ }
}
break;
@@ -946,16 +951,11 @@ Target_x86_64::Scan::global(const General_options& options,
gsym->set_needs_dynsym_value();
if (parameters->output_is_position_independent())
{
- // FIXME: R_X86_64_RELATIVE assumes a 64-bit
- // relocation.
- gold_assert(r_type == elfcpp::R_X86_64_64);
-
Reloc_section* rela_dyn =
target->rela_dyn_section(layout);
- rela_dyn->add_local(object, 0,
- elfcpp::R_X86_64_RELATIVE,
- data_shndx,
- reloc.get_r_offset(), 0);
+ rela_dyn->add_global(gsym, r_type, object, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend());
}
}
}
@@ -971,6 +971,21 @@ Target_x86_64::Scan::global(const General_options& options,
target->copy_reloc(&options, symtab, layout, object, data_shndx,
gsym, reloc);
}
+ else if (!is_pcrel && parameters->output_is_position_independent())
+ {
+ // This is not a PC-relative reference, so we need to generate
+ // a dynamic relocation. At this point, we know the symbol
+ // is not preemptible, so we can use the RELATIVE relocation.
+ Reloc_section* rela_dyn = target->rela_dyn_section(layout);
+ if (r_type == elfcpp::R_X86_64_64)
+ rela_dyn->add_local(object, 0, elfcpp::R_X86_64_RELATIVE,
+ data_shndx,
+ reloc.get_r_offset(), 0);
+ else
+ rela_dyn->add_global(gsym, r_type, object, data_shndx,
+ reloc.get_r_offset(),
+ reloc.get_r_addend());
+ }
}
break;