diff options
author | Alan Modra <amodra@gmail.com> | 2012-10-12 09:44:11 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2012-10-12 09:44:11 +0000 |
commit | c6de8ed4563e23ce1d0ee2a10a6a1ff882fa90ee (patch) | |
tree | 16de62bb9a13355b8e119942a99a7d172c9177da | |
parent | 03e25981b675b8d2bab22acca695fd16b8736e34 (diff) | |
download | fsf-binutils-gdb-c6de8ed4563e23ce1d0ee2a10a6a1ff882fa90ee.zip fsf-binutils-gdb-c6de8ed4563e23ce1d0ee2a10a6a1ff882fa90ee.tar.gz fsf-binutils-gdb-c6de8ed4563e23ce1d0ee2a10a6a1ff882fa90ee.tar.bz2 |
* 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.
-rw-r--r-- | gold/ChangeLog | 8 | ||||
-rw-r--r-- | gold/powerpc.cc | 35 |
2 files changed, 40 insertions, 3 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index cbedb79..5895962 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,13 @@ 2012-10-12 Alan Modra <amodra@gmail.com> + * 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. + +2012-10-12 Alan Modra <amodra@gmail.com> + * powerpc.cc (Output_data_plt_powerpc::add_entry, add_ifunc_entry, add_local_ifunc_entry): Revert last change. (Target_powerpc::make_plt_entry, make_local_ifunc_plt_entry): Likewise. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index fc9264e..e346ac5 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -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_process_relocs( 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_mark_symbol( { 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); } } } |