summaryrefslogtreecommitdiff
path: root/gold
diff options
context:
space:
mode:
authorAlan Modra <amodra@gmail.com>2014-12-03 16:17:23 +1030
committerAlan Modra <amodra@gmail.com>2014-12-04 09:23:59 +1030
commit1611bc4afb0f08f0aff64ec355b8d68e9f4f0a73 (patch)
tree6fbb005db969d5584029e9869561afd960a61fd7 /gold
parent858339f2b7aafe199c1cd07fc8d4a7c8130aa285 (diff)
downloadbinutils-gdb-1611bc4afb0f08f0aff64ec355b8d68e9f4f0a73.tar.gz
powerpc gold, work around pr17670
pr17670 is about an assert triggering on a branch to an undefined weak symbol, the symbol being undefined due to dropping its comdat group section. (Well sort of. The symbol is actually defined in an .opd section which isn't part of the group, but the code section the opd entry points at is dropped.) So don't assert. Also, don't make long branch stubs to such symbols, and arrange to have target-reloc.h code warn when applying relocs that use the sym. 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.
Diffstat (limited to 'gold')
-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 b98b76a9c49..8ab8387588a 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 5805c0bd769..0da355f2aa1 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 70fb3f04f9b..c4330186e5f 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;
}