* powerpc.cc (class Powerpc_relobj): Move some member functions.
(Target_powerpc::symval_for_branch): Add symtab param. Update all callers. Handle folded sections. (Target_powerpc::do_gc_add_reference): Don't cast dynamic object to Powerpc_relobj. (Global_symbol_visitor_opd::operator()): Likewise.
This commit is contained in:
parent
049109b007
commit
6c77229c00
@ -1,3 +1,12 @@
|
||||
2013-03-06 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* powerpc.cc (class Powerpc_relobj): Move some member functions.
|
||||
(Target_powerpc::symval_for_branch): Add symtab param. Update
|
||||
all callers. Handle folded sections.
|
||||
(Target_powerpc::do_gc_add_reference): Don't cast dynamic object
|
||||
to Powerpc_relobj.
|
||||
(Global_symbol_visitor_opd::operator()): Likewise.
|
||||
|
||||
2013-03-04 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* testsuite/Makefile.am (final_layout_script.lds): Add .sbss.
|
||||
|
108
gold/powerpc.cc
108
gold/powerpc.cc
@ -147,43 +147,6 @@ public:
|
||||
this->opd_ent_[ndx].discard = true;
|
||||
}
|
||||
|
||||
Access_from*
|
||||
access_from_map()
|
||||
{ return &this->access_from_map_; }
|
||||
|
||||
// Add a reference from SRC_OBJ, SRC_INDX to this object's .opd
|
||||
// section at DST_OFF.
|
||||
void
|
||||
add_reference(Object* src_obj,
|
||||
unsigned int src_indx,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
|
||||
{
|
||||
Section_id src_id(src_obj, src_indx);
|
||||
this->access_from_map_[dst_off].insert(src_id);
|
||||
}
|
||||
|
||||
// Add a reference to the code section specified by the .opd entry
|
||||
// at DST_OFF
|
||||
void
|
||||
add_gc_mark(typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
|
||||
{
|
||||
size_t ndx = this->opd_ent_ndx(dst_off);
|
||||
if (ndx >= this->opd_ent_.size())
|
||||
this->opd_ent_.resize(ndx + 1);
|
||||
this->opd_ent_[ndx].gc_mark = true;
|
||||
}
|
||||
|
||||
void
|
||||
process_gc_mark(Symbol_table* symtab)
|
||||
{
|
||||
for (size_t i = 0; i < this->opd_ent_.size(); i++)
|
||||
if (this->opd_ent_[i].gc_mark)
|
||||
{
|
||||
unsigned int shndx = this->opd_ent_[i].shndx;
|
||||
symtab->gc()->worklist().push(Section_id(this, shndx));
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
opd_valid() const
|
||||
{ return this->opd_valid_; }
|
||||
@ -222,6 +185,43 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
Access_from*
|
||||
access_from_map()
|
||||
{ return &this->access_from_map_; }
|
||||
|
||||
// Add a reference from SRC_OBJ, SRC_INDX to this object's .opd
|
||||
// section at DST_OFF.
|
||||
void
|
||||
add_reference(Object* src_obj,
|
||||
unsigned int src_indx,
|
||||
typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
|
||||
{
|
||||
Section_id src_id(src_obj, src_indx);
|
||||
this->access_from_map_[dst_off].insert(src_id);
|
||||
}
|
||||
|
||||
// Add a reference to the code section specified by the .opd entry
|
||||
// at DST_OFF
|
||||
void
|
||||
add_gc_mark(typename elfcpp::Elf_types<size>::Elf_Addr dst_off)
|
||||
{
|
||||
size_t ndx = this->opd_ent_ndx(dst_off);
|
||||
if (ndx >= this->opd_ent_.size())
|
||||
this->opd_ent_.resize(ndx + 1);
|
||||
this->opd_ent_[ndx].gc_mark = true;
|
||||
}
|
||||
|
||||
void
|
||||
process_gc_mark(Symbol_table* symtab)
|
||||
{
|
||||
for (size_t i = 0; i < this->opd_ent_.size(); i++)
|
||||
if (this->opd_ent_[i].gc_mark)
|
||||
{
|
||||
unsigned int shndx = this->opd_ent_[i].shndx;
|
||||
symtab->gc()->worklist().push(Section_id(this, shndx));
|
||||
}
|
||||
}
|
||||
|
||||
// Return offset in output GOT section that this object will use
|
||||
// as a TOC pointer. Won't be just a constant with multi-toc support.
|
||||
Address
|
||||
@ -796,7 +796,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
||||
};
|
||||
|
||||
Address
|
||||
symval_for_branch(Address value, const Sized_symbol<size>* gsym,
|
||||
symval_for_branch(const Symbol_table* symtab, Address value,
|
||||
const Sized_symbol<size>* gsym,
|
||||
Powerpc_relobj<size, big_endian>* object,
|
||||
unsigned int *dest_shndx);
|
||||
|
||||
@ -2163,7 +2164,8 @@ Target_powerpc<size, big_endian>::Branch_info::make_stub(
|
||||
if (size == 64 && is_branch_reloc(this->r_type_))
|
||||
{
|
||||
unsigned int dest_shndx;
|
||||
to = stub_table->targ()->symval_for_branch(to, gsym, this->object_,
|
||||
to = stub_table->targ()->symval_for_branch(symtab, to, gsym,
|
||||
this->object_,
|
||||
&dest_shndx);
|
||||
}
|
||||
Address delta = to - from;
|
||||
@ -5527,11 +5529,12 @@ Target_powerpc<size, big_endian>::do_gc_add_reference(
|
||||
unsigned int dst_shndx,
|
||||
Address dst_off) const
|
||||
{
|
||||
if (size != 64 || dst_obj->is_dynamic())
|
||||
return;
|
||||
|
||||
Powerpc_relobj<size, big_endian>* ppc_object
|
||||
= static_cast<Powerpc_relobj<size, big_endian>*>(dst_obj);
|
||||
if (size == 64
|
||||
&& !ppc_object->is_dynamic()
|
||||
&& dst_shndx == ppc_object->opd_shndx())
|
||||
if (dst_shndx == ppc_object->opd_shndx())
|
||||
{
|
||||
if (ppc_object->opd_valid())
|
||||
{
|
||||
@ -5637,10 +5640,12 @@ class Global_symbol_visitor_opd
|
||||
|| !sym->in_real_elf())
|
||||
return;
|
||||
|
||||
if (sym->object()->is_dynamic())
|
||||
return;
|
||||
|
||||
Powerpc_relobj<64, big_endian>* symobj
|
||||
= static_cast<Powerpc_relobj<64, big_endian>*>(sym->object());
|
||||
if (symobj->is_dynamic()
|
||||
|| symobj->opd_shndx() == 0)
|
||||
if (symobj->opd_shndx() == 0)
|
||||
return;
|
||||
|
||||
bool is_ordinary;
|
||||
@ -5827,6 +5832,7 @@ ok_lo_toc_insn(uint32_t insn)
|
||||
template<int size, bool big_endian>
|
||||
typename Target_powerpc<size, big_endian>::Address
|
||||
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,
|
||||
@ -5854,6 +5860,13 @@ Target_powerpc<size, big_endian>::symval_for_branch(
|
||||
{
|
||||
Address sec_off;
|
||||
*dest_shndx = symobj->get_opd_ent(value - opd_addr, &sec_off);
|
||||
if (symtab->is_section_folded(symobj, *dest_shndx))
|
||||
{
|
||||
Section_id folded
|
||||
= symtab->icf()->get_folded_section(symobj, *dest_shndx);
|
||||
symobj = static_cast<Powerpc_relobj<size, big_endian>*>(folded.first);
|
||||
*dest_shndx = folded.second;
|
||||
}
|
||||
Address sec_addr = symobj->get_output_section_offset(*dest_shndx);
|
||||
gold_assert(sec_addr != invalid_address);
|
||||
sec_addr += symobj->output_section(*dest_shndx)->address();
|
||||
@ -5996,8 +6009,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||
Address addend = rela.get_r_addend();
|
||||
unsigned int dest_shndx;
|
||||
Address opdent = psymval->value(object, addend);
|
||||
code = target->symval_for_branch(opdent, gsym, object,
|
||||
&dest_shndx);
|
||||
code = target->symval_for_branch(relinfo->symtab, opdent,
|
||||
gsym, object, &dest_shndx);
|
||||
bool is_ordinary;
|
||||
if (dest_shndx == 0)
|
||||
dest_shndx = gsym->shndx(&is_ordinary);
|
||||
@ -6259,7 +6272,8 @@ Target_powerpc<size, big_endian>::Relocate::relocate(
|
||||
addend = rela.get_r_addend();
|
||||
value = psymval->value(object, addend);
|
||||
if (size == 64 && is_branch_reloc(r_type))
|
||||
value = target->symval_for_branch(value, gsym, object, &dest_shndx);
|
||||
value = target->symval_for_branch(relinfo->symtab, value,
|
||||
gsym, object, &dest_shndx);
|
||||
unsigned int max_branch_offset = 0;
|
||||
if (r_type == elfcpp::R_POWERPC_REL24
|
||||
|| r_type == elfcpp::R_PPC_PLTREL24
|
||||
|
Loading…
Reference in New Issue
Block a user