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<big_endian>*> Stub_table_list;
read_arm_attributes_section<big_endian>(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<bool big_endian>
+void
+Arm_relobj<big_endian>::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.
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.
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_;
}
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);