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.
This commit is contained in:
parent
ba715d7fe4
commit
cbcb23fa01
|
@ -1,3 +1,11 @@
|
||||||
|
2014-12-04 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* 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.
|
||||||
|
|
||||||
2014-12-04 Alan Modra <amodra@gmail.com>
|
2014-12-04 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
PR 17670
|
PR 17670
|
||||||
|
|
|
@ -2657,7 +2657,7 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (max_branch_offset == 0)
|
||||||
return true;
|
return true;
|
||||||
Address from = this->object_->get_output_section_offset(this->shndx_);
|
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)
|
if (size == 64)
|
||||||
to += this->object_->ppc64_local_entry_offset(this->r_sym_);
|
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)
|
if (stub_table == NULL)
|
||||||
stub_table = this->object_->stub_table(this->shndx_);
|
stub_table = this->object_->stub_table(this->shndx_);
|
||||||
if (size == 64 && target->abiversion() < 2)
|
if (size == 64 && target->abiversion() < 2)
|
||||||
|
@ -3627,7 +3628,7 @@ class Stub_table : public Output_relaxed_input_section
|
||||||
bool
|
bool
|
||||||
can_reach_stub(Address from, unsigned int off, unsigned int r_type)
|
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)
|
if (max_branch_offset == 0)
|
||||||
return true;
|
return true;
|
||||||
gold_assert(from != invalid_address);
|
gold_assert(from != invalid_address);
|
||||||
|
@ -7197,7 +7198,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||||
else if (!has_stub_value)
|
else if (!has_stub_value)
|
||||||
{
|
{
|
||||||
Address addend = 0;
|
Address addend = 0;
|
||||||
if (r_type != elfcpp::R_PPC_PLTREL24)
|
if (!(size == 32 && r_type == elfcpp::R_PPC_PLTREL24))
|
||||||
addend = rela.get_r_addend();
|
addend = rela.get_r_addend();
|
||||||
value = psymval->value(object, addend);
|
value = psymval->value(object, addend);
|
||||||
if (size == 64 && is_branch_reloc(r_type))
|
if (size == 64 && is_branch_reloc(r_type))
|
||||||
|
@ -7216,7 +7217,7 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||||
&value, &dest_shndx);
|
&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
|
if (max_branch_offset != 0
|
||||||
&& value - address + max_branch_offset >= 2 * max_branch_offset)
|
&& value - address + max_branch_offset >= 2 * max_branch_offset)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue