From 99e5bff2f9e0ccdba7d78f431f177d8f83871ddd Mon Sep 17 00:00:00 2001 From: Doug Kwan Date: Tue, 12 Jan 2010 07:22:56 +0000 Subject: 2010-01-11 Doug Kwan * arm.cc (Arm_relobj::do_gc_process_relocs): New method. (Target_arm::do_finalize_sections): Define special EXIDX section symbols only if referenced. * gc.h (Garbage_collection::add_reference): New method. (gc_process_relocs): Use Garbage_collection::add_reference to avoid code duplication. --- gold/ChangeLog | 9 +++++++++ gold/arm.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++-- gold/gc.h | 30 +++++++++++++++++------------- 3 files changed, 70 insertions(+), 15 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index faec2f9..49b7a10 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,12 @@ +2010-01-11 Doug Kwan + + * arm.cc (Arm_relobj::do_gc_process_relocs): New method. + (Target_arm::do_finalize_sections): Define special EXIDX section + symbols only if referenced. + * gc.h (Garbage_collection::add_reference): New method. + (gc_process_relocs): Use Garbage_collection::add_reference to avoid + code duplication. + 2010-01-11 Ian Lance Taylor * script.cc (Version_script_info::build_expression_list_lookup): diff --git a/gold/arm.cc b/gold/arm.cc index 694ef93..e6343ec 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -1178,6 +1178,10 @@ class Arm_relobj : public Sized_relobj<32, big_endian> void do_read_symbols(Read_symbols_data* sd); + // Process relocs for garbage collection. + void + do_gc_process_relocs(Symbol_table*, Layout*, Read_relocs_data*); + private: // List of stub tables. typedef std::vector*> Stub_table_list; @@ -4235,6 +4239,44 @@ Arm_relobj::do_read_symbols(Read_symbols_data* sd) read_arm_attributes_section(this, sd); } +// Process relocations for garbage collection. The ARM target uses .ARM.exidx +// sections for unwinding. These sections are referenced implicitly by +// text sections linked in the section headers. If we ignore these implict +// references, the .ARM.exidx sections and any .ARM.extab sections they use +// will be garbage-collected incorrectly. Hence we override the same function +// in the base class to handle these implicit references. + +template +void +Arm_relobj::do_gc_process_relocs(Symbol_table* symtab, + Layout* layout, + Read_relocs_data* rd) +{ + // First, call base class method to process relocations in this object. + Sized_relobj<32, big_endian>::do_gc_process_relocs(symtab, layout, rd); + + unsigned int shnum = this->shnum(); + const unsigned int shdr_size = elfcpp::Elf_sizes<32>::shdr_size; + const unsigned char* pshdrs = this->get_view(this->elf_file()->shoff(), + shnum * shdr_size, + true, true); + + // Scan section headers for sections of type SHT_ARM_EXIDX. Add references + // to these from the linked text sections. + const unsigned char* ps = pshdrs + shdr_size; + for (unsigned int i = 1; i < shnum; ++i, ps += shdr_size) + { + elfcpp::Shdr<32, big_endian> shdr(ps); + if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX) + { + // Found an .ARM.exidx section, add it to the set of reachable + // sections from its linked text section. + unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link()); + symtab->gc()->add_reference(this, text_shndx, this, i); + } + } +} + // Arm_dynobj methods. // Read the symbol information. @@ -5081,12 +5123,12 @@ Target_arm::do_finalize_sections( Symbol_table::PREDEFINED, exidx_section, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0, - false, false); + false, true); symtab->define_in_output_data("__exidx_end", NULL, Symbol_table::PREDEFINED, exidx_section, 0, 0, elfcpp::STT_OBJECT, elfcpp::STB_GLOBAL, elfcpp::STV_HIDDEN, 0, - true, false); + true, true); // For the ARM target, we need to add a PT_ARM_EXIDX segment for // the .ARM.exidx section. diff --git a/gold/gc.h b/gold/gc.h index 838b7db..3885d1a 100644 --- a/gold/gc.h +++ b/gold/gc.h @@ -108,6 +108,21 @@ class Garbage_collection Section_id secn) { this->cident_sections_[section_name].insert(secn); } + // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to + // DST_SHNDX-th section of DST_OBJECT. + void + add_reference(Object* src_object, unsigned int src_shndx, + Object* dst_object, unsigned int dst_shndx) + { + Section_id src_id(src_object, src_shndx); + Section_id dst_id(dst_object, dst_shndx); + Section_ref::iterator p = this->section_reloc_map_.find(src_id); + if (p == this->section_reloc_map_.end()) + this->section_reloc_map_[src_id].insert(dst_id); + else + p->second.insert(dst_id); + } + private: Worklist_type work_list_; @@ -261,25 +276,14 @@ gc_process_relocs( } if (parameters->options().gc_sections()) { - Section_id src_id(src_obj, src_indx); - Section_id dst_id(dst_obj, dst_indx); - Garbage_collection::Section_ref::iterator map_it; - map_it = symtab->gc()->section_reloc_map().find(src_id); - if (map_it == symtab->gc()->section_reloc_map().end()) - { - symtab->gc()->section_reloc_map()[src_id].insert(dst_id); - } - else - { - Garbage_collection::Sections_reachable& v(map_it->second); - v.insert(dst_id); - } + symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx); if (cident_section_name != NULL) { Garbage_collection::Cident_section_map::iterator ele = symtab->gc()->cident_sections()->find(std::string(cident_section_name)); if (ele == symtab->gc()->cident_sections()->end()) continue; + Section_id src_id(src_obj, src_indx); Garbage_collection::Sections_reachable& v(symtab->gc()->section_reloc_map()[src_id]); Garbage_collection::Sections_reachable& cident_secn(ele->second); -- cgit v1.1