diff options
author | Alan Modra <amodra@gmail.com> | 2021-08-26 12:17:51 +0930 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2021-09-18 08:20:11 +0930 |
commit | 5cdb4f14426a99ec8fcba843fa503efdc55fa078 (patch) | |
tree | a3f47ff28cc2d40165b4f61a2e06cebe919990b1 /gold/powerpc.cc | |
parent | e4d49a0f908415edb7a7e718ef2008a96dd43f9b (diff) | |
download | gdb-5cdb4f14426a99ec8fcba843fa503efdc55fa078.zip gdb-5cdb4f14426a99ec8fcba843fa503efdc55fa078.tar.gz gdb-5cdb4f14426a99ec8fcba843fa503efdc55fa078.tar.bz2 |
[GOLD] PowerPC64 support for sym+addend GOT entries
Pass addends to all the GOT handling functions, plus remove some
extraneous asserts.
PR 28192
* powerpc.cc (Output_data_got_powerpc): Add addend parameter to
all methods creating got entries.
(Target_powerpc::Scan::local): Pass reloc addend to got handling
functions, and when creating dynamic got relocations.
(Target_powerpc::Scan::global): Likewise.
(Target_powerpc::Relocate::relocate): Likewise. Remove extraneous
assertions.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r-- | gold/powerpc.cc | 148 |
1 files changed, 74 insertions, 74 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 0b64059..0cee975 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -2970,77 +2970,85 @@ public: // Override all the Output_data_got methods we use so as to first call // reserve_ent(). bool - add_global(Symbol* gsym, unsigned int got_type) + add_global(Symbol* gsym, unsigned int got_type, uint64_t addend) { this->reserve_ent(); - return Output_data_got<size, big_endian>::add_global(gsym, got_type); + return Output_data_got<size, big_endian>::add_global(gsym, got_type, + addend); } bool - add_global_plt(Symbol* gsym, unsigned int got_type) + add_global_plt(Symbol* gsym, unsigned int got_type, uint64_t addend) { this->reserve_ent(); - return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type); + return Output_data_got<size, big_endian>::add_global_plt(gsym, got_type, + addend); } bool - add_global_tls(Symbol* gsym, unsigned int got_type) - { return this->add_global_plt(gsym, got_type); } + add_global_tls(Symbol* gsym, unsigned int got_type, uint64_t addend) + { return this->add_global_plt(gsym, got_type, addend); } void add_global_with_rel(Symbol* gsym, unsigned int got_type, - Output_data_reloc_generic* rel_dyn, unsigned int r_type) + Output_data_reloc_generic* rel_dyn, + unsigned int r_type, uint64_t addend) { this->reserve_ent(); Output_data_got<size, big_endian>:: - add_global_with_rel(gsym, got_type, rel_dyn, r_type); + add_global_with_rel(gsym, got_type, rel_dyn, r_type, addend); } void add_global_pair_with_rel(Symbol* gsym, unsigned int got_type, Output_data_reloc_generic* rel_dyn, - unsigned int r_type_1, unsigned int r_type_2) + unsigned int r_type_1, unsigned int r_type_2, + uint64_t addend) { if (gsym->has_got_offset(got_type)) return; this->reserve_ent(2); Output_data_got<size, big_endian>:: - add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2); + add_global_pair_with_rel(gsym, got_type, rel_dyn, r_type_1, r_type_2, + addend); } bool - add_local(Relobj* object, unsigned int sym_index, unsigned int got_type) + add_local(Relobj* object, unsigned int sym_index, unsigned int got_type, + uint64_t addend) { this->reserve_ent(); return Output_data_got<size, big_endian>::add_local(object, sym_index, - got_type); + got_type, addend); } bool - add_local_plt(Relobj* object, unsigned int sym_index, unsigned int got_type) + add_local_plt(Relobj* object, unsigned int sym_index, + unsigned int got_type, uint64_t addend) { this->reserve_ent(); return Output_data_got<size, big_endian>::add_local_plt(object, sym_index, - got_type); + got_type, addend); } bool - add_local_tls(Relobj* object, unsigned int sym_index, unsigned int got_type) - { return this->add_local_plt(object, sym_index, got_type); } + add_local_tls(Relobj* object, unsigned int sym_index, + unsigned int got_type, uint64_t addend) + { return this->add_local_plt(object, sym_index, got_type, addend); } void add_local_tls_pair(Relobj* object, unsigned int sym_index, unsigned int got_type, Output_data_reloc_generic* rel_dyn, - unsigned int r_type) + unsigned int r_type, uint64_t addend) { - if (object->local_has_got_offset(sym_index, got_type)) + if (object->local_has_got_offset(sym_index, got_type, addend)) return; this->reserve_ent(2); Output_data_got<size, big_endian>:: - add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type); + add_local_tls_pair(object, sym_index, got_type, rel_dyn, r_type, addend); } unsigned int @@ -8195,29 +8203,30 @@ Target_powerpc<size, big_endian>::Scan::local( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); if (!parameters->options().output_is_position_independent()) { if (is_ifunc && (size == 32 || target->abiversion() >= 2)) - got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD); + got->add_local_plt(object, r_sym, GOT_TYPE_STANDARD, addend); else - got->add_local(object, r_sym, GOT_TYPE_STANDARD); + got->add_local(object, r_sym, GOT_TYPE_STANDARD, addend); } - else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)) + else if (!object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD, addend)) { // If we are generating a shared object or a pie, this // symbol's GOT entry will be set by a dynamic relocation. unsigned int off; off = got->add_constant(0); - object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off); + object->set_local_got_offset(r_sym, GOT_TYPE_STANDARD, off, addend); Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout, is_ifunc); unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE : elfcpp::R_POWERPC_RELATIVE); rela_dyn->add_local_relative(object, r_sym, dynrel, - got, off, 0, false); + got, off, addend, false); } } break; @@ -8246,9 +8255,11 @@ Target_powerpc<size, big_endian>::Scan::local( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); Reloc_section* rela_dyn = target->rela_dyn_section(layout); got->add_local_tls_pair(object, r_sym, GOT_TYPE_TLSGD, - rela_dyn, elfcpp::R_POWERPC_DTPMOD); + rela_dyn, elfcpp::R_POWERPC_DTPMOD, + addend); } else if (tls_type == tls::TLSOPT_TO_LE) { @@ -8296,7 +8307,8 @@ Target_powerpc<size, big_endian>::Scan::local( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); - got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); + got->add_local_tls(object, r_sym, GOT_TYPE_DTPREL, addend); } break; @@ -8310,17 +8322,18 @@ Target_powerpc<size, big_endian>::Scan::local( if (tls_type == tls::TLSOPT_NONE) { unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info()); - if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL)) + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); + if (!object->local_has_got_offset(r_sym, GOT_TYPE_TPREL, addend)) { Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); unsigned int off = got->add_constant(0); - object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off); + object->set_local_got_offset(r_sym, GOT_TYPE_TPREL, off, addend); Reloc_section* rela_dyn = target->rela_dyn_section(layout); rela_dyn->add_symbolless_local_addend(object, r_sym, elfcpp::R_POWERPC_TPREL, - got, off, 0); + got, off, addend); } } else if (tls_type == tls::TLSOPT_TO_LE) @@ -8980,22 +8993,23 @@ Target_powerpc<size, big_endian>::Scan::global( { // The symbol requires a GOT entry. Output_data_got_powerpc<size, big_endian>* got; + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); got = target->got_section(symtab, layout); if (gsym->final_value_is_known()) { if (is_ifunc && (size == 32 || target->abiversion() >= 2)) - got->add_global_plt(gsym, GOT_TYPE_STANDARD); + got->add_global_plt(gsym, GOT_TYPE_STANDARD, addend); else - got->add_global(gsym, GOT_TYPE_STANDARD); + got->add_global(gsym, GOT_TYPE_STANDARD, addend); } - else if (!gsym->has_got_offset(GOT_TYPE_STANDARD)) + else if (!gsym->has_got_offset(GOT_TYPE_STANDARD, addend)) { // If we are generating a shared object or a pie, this // symbol's GOT entry will be set by a dynamic relocation. unsigned int off = got->add_constant(0); - gsym->set_got_offset(GOT_TYPE_STANDARD, off); + gsym->set_got_offset(GOT_TYPE_STANDARD, off, addend); Reloc_section* rela_dyn = target->rela_dyn_section(symtab, layout, is_ifunc); @@ -9008,12 +9022,13 @@ Target_powerpc<size, big_endian>::Scan::global( { unsigned int dynrel = (is_ifunc ? elfcpp::R_POWERPC_IRELATIVE : elfcpp::R_POWERPC_RELATIVE); - rela_dyn->add_global_relative(gsym, dynrel, got, off, 0, false); + rela_dyn->add_global_relative(gsym, dynrel, got, off, + addend, false); } else { unsigned int dynrel = elfcpp::R_POWERPC_GLOB_DAT; - rela_dyn->add_global(gsym, dynrel, got, off, 0); + rela_dyn->add_global(gsym, dynrel, got, off, addend); } } } @@ -9046,9 +9061,11 @@ Target_powerpc<size, big_endian>::Scan::global( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); Reloc_section* rela_dyn = target->rela_dyn_section(layout); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); got->add_global_pair_with_rel(gsym, GOT_TYPE_TLSGD, rela_dyn, elfcpp::R_POWERPC_DTPMOD, - elfcpp::R_POWERPC_DTPREL); + elfcpp::R_POWERPC_DTPREL, + addend); } else if (tls_type == tls::TLSOPT_TO_IE) { @@ -9057,11 +9074,12 @@ Target_powerpc<size, big_endian>::Scan::global( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); Reloc_section* rela_dyn = target->rela_dyn_section(layout); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); if (gsym->is_undefined() || gsym->is_from_dynobj()) { got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn, - elfcpp::R_POWERPC_TPREL); + elfcpp::R_POWERPC_TPREL, addend); } else { @@ -9069,7 +9087,7 @@ Target_powerpc<size, big_endian>::Scan::global( gsym->set_got_offset(GOT_TYPE_TPREL, off); unsigned int dynrel = elfcpp::R_POWERPC_TPREL; rela_dyn->add_symbolless_global_addend(gsym, dynrel, - got, off, 0); + got, off, addend); } } ppc_object->set_tls_marker(); @@ -9119,15 +9137,16 @@ Target_powerpc<size, big_endian>::Scan::global( { Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); if (!gsym->final_value_is_known() && (gsym->is_from_dynobj() || gsym->is_undefined() || gsym->is_preemptible())) got->add_global_with_rel(gsym, GOT_TYPE_DTPREL, target->rela_dyn_section(layout), - elfcpp::R_POWERPC_DTPREL); + elfcpp::R_POWERPC_DTPREL, addend); else - got->add_global_tls(gsym, GOT_TYPE_DTPREL); + got->add_global_tls(gsym, GOT_TYPE_DTPREL, addend); } break; @@ -9146,11 +9165,12 @@ Target_powerpc<size, big_endian>::Scan::global( Output_data_got_powerpc<size, big_endian>* got = target->got_section(symtab, layout); Reloc_section* rela_dyn = target->rela_dyn_section(layout); + uint64_t addend = size == 32 ? 0 : reloc.get_r_addend(); if (gsym->is_undefined() || gsym->is_from_dynobj()) { got->add_global_with_rel(gsym, GOT_TYPE_TPREL, rela_dyn, - elfcpp::R_POWERPC_TPREL); + elfcpp::R_POWERPC_TPREL, addend); } else { @@ -9158,7 +9178,7 @@ Target_powerpc<size, big_endian>::Scan::global( gsym->set_got_offset(GOT_TYPE_TPREL, off); unsigned int dynrel = elfcpp::R_POWERPC_TPREL; rela_dyn->add_symbolless_global_addend(gsym, dynrel, - got, off, 0); + got, off, addend); } } } @@ -10655,16 +10675,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate( } else if (is_got_reloc(r_type)) { + uint64_t addend = size == 32 ? 0 : rela.get_r_addend(); if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(GOT_TYPE_STANDARD)); - value = gsym->got_offset(GOT_TYPE_STANDARD); - } + value = gsym->got_offset(GOT_TYPE_STANDARD, addend); else - { - gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD)); - value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD); - } + value = object->local_got_offset(r_sym, GOT_TYPE_STANDARD, addend); if (r_type == elfcpp::R_PPC64_GOT_PCREL34) value += target->got_section()->address(); else @@ -10764,16 +10779,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate( got_type = GOT_TYPE_TPREL; if (got_type != GOT_TYPE_STANDARD) { + uint64_t addend = size == 32 ? 0 : rela.get_r_addend(); if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(got_type)); - value = gsym->got_offset(got_type); - } + value = gsym->got_offset(got_type, addend); else - { - gold_assert(object->local_has_got_offset(r_sym, got_type)); - value = object->local_got_offset(r_sym, got_type); - } + value = object->local_got_offset(r_sym, got_type, addend); if (r_type == elfcpp::R_PPC64_GOT_TLSGD_PCREL34) value += target->got_section()->address(); else @@ -10920,16 +10930,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate( { // Accesses relative to a local dynamic sequence address, // no optimisation here. + uint64_t addend = size == 32 ? 0 : rela.get_r_addend(); if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(GOT_TYPE_DTPREL)); - value = gsym->got_offset(GOT_TYPE_DTPREL); - } + value = gsym->got_offset(GOT_TYPE_DTPREL, addend); else - { - gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_DTPREL)); - value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL); - } + value = object->local_got_offset(r_sym, GOT_TYPE_DTPREL, addend); if (r_type == elfcpp::R_PPC64_GOT_DTPREL_PCREL34) value += target->got_section()->address(); else @@ -10946,16 +10951,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate( tls::Tls_optimization tls_type = target->optimize_tls_ie(final); if (tls_type == tls::TLSOPT_NONE) { + uint64_t addend = size == 32 ? 0 : rela.get_r_addend(); if (gsym != NULL) - { - gold_assert(gsym->has_got_offset(GOT_TYPE_TPREL)); - value = gsym->got_offset(GOT_TYPE_TPREL); - } + value = gsym->got_offset(GOT_TYPE_TPREL, addend); else - { - gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_TPREL)); - value = object->local_got_offset(r_sym, GOT_TYPE_TPREL); - } + value = object->local_got_offset(r_sym, GOT_TYPE_TPREL, addend); if (r_type == elfcpp::R_PPC64_GOT_TPREL_PCREL34) value += target->got_section()->address(); else |