diff options
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r-- | gold/powerpc.cc | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 244c221..d529519 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -9734,6 +9734,8 @@ Target_powerpc<size, big_endian>::relocate_relocs( gold_assert(got2_addend != invalid_address); } + const bool relocatable = parameters->options().relocatable(); + unsigned char* pwrite = reloc_view; bool zap_next = false; for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) @@ -9829,7 +9831,7 @@ Target_powerpc<size, big_endian>::relocate_relocs( // In an object file, r_offset is an offset within the section. // In an executable or dynamic object, generated by // --emit-relocs, r_offset is an absolute address. - if (!parameters->options().relocatable()) + if (!relocatable) { offset += view_address; if (static_cast<Address>(offset_in_output_section) != invalid_address) @@ -9842,8 +9844,15 @@ Target_powerpc<size, big_endian>::relocate_relocs( else if (strategy == Relocatable_relocs::RELOC_ADJUST_FOR_SECTION_RELA) { const Symbol_value<size>* psymval = object->local_symbol(orig_r_sym); - gold_assert(os != NULL); - addend = psymval->value(object, addend) - os->address(); + addend = psymval->value(object, addend); + // In a relocatable link, the symbol value is relative to + // the start of the output section. For a non-relocatable + // link, we need to adjust the addend. + if (!relocatable) + { + gold_assert(os != NULL); + addend -= os->address(); + } } else if (strategy == Relocatable_relocs::RELOC_SPECIAL) { @@ -9866,7 +9875,7 @@ Target_powerpc<size, big_endian>::relocate_relocs( else gold_unreachable(); - if (!parameters->options().relocatable()) + if (!relocatable) { if (r_type == elfcpp::R_POWERPC_GOT_TLSGD16 || r_type == elfcpp::R_POWERPC_GOT_TLSGD16_LO |