This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[GOLD] powerpc --gc-sections --shared
- From: Alan Modra <amodra at gmail dot com>
- To: binutils at sourceware dot org
- Date: Fri, 12 Oct 2012 20:12:52 +1030
- Subject: [GOLD] powerpc --gc-sections --shared
This corrects a problem with --gc-sections on powerpc64.
gc_mark_symbol can be called during Add_symbols, which happens before
.opd relocs are scanned to set up .opd info. In that case, we need to
delay marking function sections.
* powerpc.cc (Powerpc_relobj::add_gc_mark, process_gc_mark): New.
(struct Opd_ent): Make "discard" a bit field. Add "gc_mark".
(Target_powerpc::do_gc_mark_symbol): Delay marking function code
section if scan_opd_relocs not yet called.
(Target_powerpc::gc_process_relocs): Call process_gc_mark.
Index: gold/powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.62
diff -u -p -r1.62 powerpc.cc
--- gold/powerpc.cc 12 Oct 2012 09:39:19 -0000 1.62
+++ gold/powerpc.cc 12 Oct 2012 09:39:57 -0000
@@ -154,6 +154,28 @@ public:
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_; }
@@ -200,7 +222,8 @@ private:
struct Opd_ent
{
unsigned int shndx;
- bool discard;
+ bool discard : 1;
+ bool gc_mark : 1;
Offset off;
};
@@ -3499,6 +3522,7 @@ Target_powerpc<size, big_endian>::gc_pro
p->second.clear();
}
ppc_object->access_from_map()->clear();
+ ppc_object->process_gc_mark(symtab);
// Don't look at .opd relocs as .opd will reference everything.
return;
}
@@ -3571,8 +3595,13 @@ Target_powerpc<size, big_endian>::do_gc_
{
Sized_symbol<size>* gsym = symtab->get_sized_symbol<size>(sym);
Address dst_off = gsym->value();
- unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
- symtab->gc()->worklist().push(Section_id(ppc_object, dst_indx));
+ if (ppc_object->opd_valid())
+ {
+ unsigned int dst_indx = ppc_object->get_opd_ent(dst_off);
+ symtab->gc()->worklist().push(Section_id(ppc_object, dst_indx));
+ }
+ else
+ ppc_object->add_gc_mark(dst_off);
}
}
}
--
Alan Modra
Australia Development Lab, IBM