aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gold/ChangeLog13
-rw-r--r--gold/powerpc.cc54
-rw-r--r--gold/symtab.cc1
3 files changed, 44 insertions, 24 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog
index b98b76a..8ab8387 100644
--- a/gold/ChangeLog
+++ b/gold/ChangeLog
@@ -1,3 +1,16 @@
+2014-12-04 Alan Modra <amodra@gmail.com>
+
+ PR 17670
+ * symtab.cc (Symbol::set_undefined): Remove assertion.
+ * powerpc.cc (Target_powerpc::symval_for_branch): Don't assert
+ on symbols defined in discarded sections, instead return false.
+ Rearrange params, update all callers.
+ (Target_powerpc::Branch_info::make_stub): Don't make stubs for
+ branches to syms in discarded sections.
+ (Global_symbol_visitor_opd::operator()): Set discarded opd syms
+ undefined and flag as discarded.
+ (Target_powerpc::Relocate::relocate): Localize variable.
+
2014-12-03 H.J. Lu <hongjiu.lu@intel.com>
PR gold/17675
diff --git a/gold/powerpc.cc b/gold/powerpc.cc
index 5805c0bd..0da355f 100644
--- a/gold/powerpc.cc
+++ b/gold/powerpc.cc
@@ -1035,11 +1035,11 @@ class Target_powerpc : public Sized_target<size, big_endian>
bool issued_non_pic_error_;
};
- Address
- symval_for_branch(const Symbol_table* symtab, Address value,
+ bool
+ symval_for_branch(const Symbol_table* symtab,
const Sized_symbol<size>* gsym,
Powerpc_relobj<size, big_endian>* object,
- unsigned int *dest_shndx);
+ Address *value, unsigned int *dest_shndx);
// The class which implements relocation.
class Relocate : protected Track_tls
@@ -2717,8 +2717,9 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
if (size == 64 && target->abiversion() < 2)
{
unsigned int dest_shndx;
- to = target->symval_for_branch(symtab, to, gsym,
- this->object_, &dest_shndx);
+ if (!target->symval_for_branch(symtab, gsym, this->object_,
+ &to, &dest_shndx))
+ return true;
}
Address delta = to - from;
if (delta + max_branch_offset >= 2 * max_branch_offset)
@@ -6549,7 +6550,11 @@ class Global_symbol_visitor_opd
unsigned int shndx = sym->shndx(&is_ordinary);
if (shndx == symobj->opd_shndx()
&& symobj->get_opd_discard(sym->value()))
- sym->set_symtab_index(-1U);
+ {
+ sym->set_undefined();
+ sym->set_is_defined_in_discarded_section();
+ sym->set_symtab_index(-1U);
+ }
}
};
@@ -6727,12 +6732,12 @@ ok_lo_toc_insn(uint32_t insn)
// Return the value to use for a branch relocation.
template<int size, bool big_endian>
-typename Target_powerpc<size, big_endian>::Address
+bool
Target_powerpc<size, big_endian>::symval_for_branch(
const Symbol_table* symtab,
- Address value,
const Sized_symbol<size>* gsym,
Powerpc_relobj<size, big_endian>* object,
+ Address *value,
unsigned int *dest_shndx)
{
if (size == 32 || this->abiversion() >= 2)
@@ -6744,20 +6749,20 @@ Target_powerpc<size, big_endian>::symval_for_branch(
Powerpc_relobj<size, big_endian>* symobj = object;
if (gsym != NULL
&& gsym->source() != Symbol::FROM_OBJECT)
- return value;
+ return true;
if (gsym != NULL)
symobj = static_cast<Powerpc_relobj<size, big_endian>*>(gsym->object());
unsigned int shndx = symobj->opd_shndx();
if (shndx == 0)
- return value;
+ return true;
Address opd_addr = symobj->get_output_section_offset(shndx);
if (opd_addr == invalid_address)
- return value;
+ return true;
opd_addr += symobj->output_section_address(shndx);
- if (value >= opd_addr && value < opd_addr + symobj->section_size(shndx))
+ if (*value >= opd_addr && *value < opd_addr + symobj->section_size(shndx))
{
Address sec_off;
- *dest_shndx = symobj->get_opd_ent(value - opd_addr, &sec_off);
+ *dest_shndx = symobj->get_opd_ent(*value - opd_addr, &sec_off);
if (symtab->is_section_folded(symobj, *dest_shndx))
{
Section_id folded
@@ -6766,11 +6771,13 @@ Target_powerpc<size, big_endian>::symval_for_branch(
*dest_shndx = folded.second;
}
Address sec_addr = symobj->get_output_section_offset(*dest_shndx);
- gold_assert(sec_addr != invalid_address);
+ if (sec_addr == invalid_address)
+ return false;
+
sec_addr += symobj->output_section(*dest_shndx)->address();
- value = sec_addr + sec_off;
+ *value = sec_addr + sec_off;
}
- return value;
+ return true;
}
// Perform a relocation.
@@ -6930,10 +6937,9 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
if (target->abiversion() < 2)
{
Address addend = rela.get_r_addend();
- Address opdent = psymval->value(object, addend);
- code = target->symval_for_branch(relinfo->symtab,
- opdent, gsym, object,
- &dest_shndx);
+ code = psymval->value(object, addend);
+ target->symval_for_branch(relinfo->symtab, gsym, object,
+ &code, &dest_shndx);
}
bool is_ordinary;
if (dest_shndx == 0)
@@ -7191,7 +7197,6 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
else if (!has_stub_value)
{
Address addend = 0;
- unsigned int dest_shndx;
if (r_type != elfcpp::R_PPC_PLTREL24)
addend = rela.get_r_addend();
value = psymval->value(object, addend);
@@ -7205,8 +7210,11 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
value += object->ppc64_local_entry_offset(r_sym);
}
else
- value = target->symval_for_branch(relinfo->symtab, value,
- gsym, object, &dest_shndx);
+ {
+ unsigned int dest_shndx;
+ target->symval_for_branch(relinfo->symtab, gsym, object,
+ &value, &dest_shndx);
+ }
}
unsigned long max_branch_offset = max_branch_delta(r_type);
if (max_branch_offset != 0
diff --git a/gold/symtab.cc b/gold/symtab.cc
index 70fb3f0..c433018 100644
--- a/gold/symtab.cc
+++ b/gold/symtab.cc
@@ -547,7 +547,6 @@ Symbol::set_output_segment(Output_segment* os, Segment_offset_base base)
void
Symbol::set_undefined()
{
- gold_assert(this->is_predefined_);
this->source_ = IS_UNDEFINED;
this->is_predefined_ = false;
}