diff options
author | Ian Lance Taylor <iant@google.com> | 2007-11-02 04:08:52 +0000 |
---|---|---|
committer | Ian Lance Taylor <iant@google.com> | 2007-11-02 04:08:52 +0000 |
commit | 86849f1facff8e5639c539a6e455575f25649028 (patch) | |
tree | e914f61eb7f0245374ee8aaede2a63dddddb16cc /gold/x86_64.cc | |
parent | fe906b004d1558c79aee1d74f063b7d2cf8d08f5 (diff) | |
download | gdb-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.cc | 41 |
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; |