diff options
author | Alan Modra <amodra@gmail.com> | 2014-12-04 21:10:40 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2014-12-04 21:17:54 +1030 |
commit | cbcb23fa01027a7fe1be938d58ef8e7a60b5fb7e (patch) | |
tree | 38d9034618f627b69f3305d7fb740e7fd8eb5306 /gold/powerpc.cc | |
parent | ba715d7fe49c8a59660fbd571b935b29eb7cfbdb (diff) | |
download | gdb-cbcb23fa01027a7fe1be938d58ef8e7a60b5fb7e.zip gdb-cbcb23fa01027a7fe1be938d58ef8e7a60b5fb7e.tar.gz gdb-cbcb23fa01027a7fe1be938d58ef8e7a60b5fb7e.tar.bz2 |
PowerPC gold, fix 32-bit branch address arithmetic
Mixing 64-bit and 32-bit types led to the wrong promotions. Keep
calculation in same type. Also fix a case where PLTREL25 reloc addend
should be ignored.
* Powerpc.cc (Target_powerpc::Branch_info::make_stub): Ignore
addend of PLTREL24 reloc when not generating a plt stub. Make
max_branch_offset an "Address".
(Stub_table::can_read_stub): Make max_branch_offset an "Address".
(Target_powerpc::Relocate::relocate): Likewise.
Diffstat (limited to 'gold/powerpc.cc')
-rw-r--r-- | gold/powerpc.cc | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 0da355f..1407a0e 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -2657,7 +2657,7 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub( } else { - unsigned long max_branch_offset = max_branch_delta(this->r_type_); + Address max_branch_offset = max_branch_delta(this->r_type_); if (max_branch_offset == 0) return true; Address from = this->object_->get_output_section_offset(this->shndx_); @@ -2711,7 +2711,8 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub( if (size == 64) to += this->object_->ppc64_local_entry_offset(this->r_sym_); } - to += this->addend_; + if (!(size == 32 && this->r_type_ == elfcpp::R_PPC_PLTREL24)) + to += this->addend_; if (stub_table == NULL) stub_table = this->object_->stub_table(this->shndx_); if (size == 64 && target->abiversion() < 2) @@ -3627,7 +3628,7 @@ class Stub_table : public Output_relaxed_input_section bool can_reach_stub(Address from, unsigned int off, unsigned int r_type) { - unsigned long max_branch_offset = max_branch_delta(r_type); + Address max_branch_offset = max_branch_delta(r_type); if (max_branch_offset == 0) return true; gold_assert(from != invalid_address); @@ -7197,7 +7198,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate( else if (!has_stub_value) { Address addend = 0; - if (r_type != elfcpp::R_PPC_PLTREL24) + if (!(size == 32 && r_type == elfcpp::R_PPC_PLTREL24)) addend = rela.get_r_addend(); value = psymval->value(object, addend); if (size == 64 && is_branch_reloc(r_type)) @@ -7216,7 +7217,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate( &value, &dest_shndx); } } - unsigned long max_branch_offset = max_branch_delta(r_type); + Address max_branch_offset = max_branch_delta(r_type); if (max_branch_offset != 0 && value - address + max_branch_offset >= 2 * max_branch_offset) { |