X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gold%2Fgc.h;h=78ead4132f9a533c1963ff3e3b71db71cb713331;hb=369c9167d47e69aad2e260cc1db17f8c894c138b;hp=3885d1a23a8d3f4763263c4009e5456385b236ed;hpb=99e5bff2f9e0ccdba7d78f431f177d8f83871ddd;p=deliverable%2Fbinutils-gdb.git diff --git a/gold/gc.h b/gold/gc.h index 3885d1a23a..78ead4132f 100644 --- a/gold/gc.h +++ b/gold/gc.h @@ -1,6 +1,6 @@ // gc.h -- garbage collection of unused sections -// Copyright 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2009-2018 Free Software Foundation, Inc. // Written by Sriraman Tallam . // This file is part of gold. @@ -23,11 +23,11 @@ #ifndef GOLD_GC_H #define GOLD_GC_H -#include #include #include "elfcpp.h" #include "symtab.h" +#include "object.h" #include "icf.h" namespace gold @@ -36,30 +36,19 @@ namespace gold class Object; template -class Sized_relobj; - -template -class Reloc_types; +class Sized_relobj_file; class Output_section; class General_options; class Layout; -typedef std::pair Section_id; - class Garbage_collection { - struct Section_id_hash - { - size_t operator()(const Section_id& loc) const - { return reinterpret_cast(loc.first) ^ loc.second; } - }; - public: typedef Unordered_set Sections_reachable; typedef std::map Section_ref; - typedef std::queue Worklist_type; + typedef std::vector Worklist_type; // This maps the name of the section which can be represented as a C // identifier (cident) to the list of sections that have that name. // Different object files can have cident sections with the same name. @@ -95,7 +84,7 @@ class Garbage_collection do_transitive_closure(); bool - is_section_garbage(Object* obj, unsigned int shndx) + is_section_garbage(Relobj* obj, unsigned int shndx) { return (this->referenced_list().find(Section_id(obj, shndx)) == this->referenced_list().end()); } @@ -111,16 +100,13 @@ class Garbage_collection // 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) + add_reference(Relobj* src_object, unsigned int src_shndx, + Relobj* 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); + Sections_reachable& reachable = this->section_reloc_map_[src_id]; + reachable.insert(dst_id); } private: @@ -158,81 +144,138 @@ struct Symbols_data section_size_type symbol_names_size; }; +// Relocations of type SHT_REL store the addend value in their bytes. +// This function returns the size of the embedded addend which is +// nothing but the size of the relocation. + +template +inline unsigned int +get_embedded_addend_size(int r_type, Relobj* obj) +{ + if (Classify_reloc::sh_type == elfcpp::SHT_REL) + return Classify_reloc::get_size_for_reloc(r_type, obj); + return 0; +} + // This function implements the generic part of reloc // processing to map a section to all the sections it // references through relocs. It is called only during // garbage collection (--gc-sections) and identical code // folding (--icf). -template +template inline void gc_process_relocs( Symbol_table* symtab, Layout*, - Target_type* , - Sized_relobj* src_obj, + Target_type* target, + Sized_relobj_file* src_obj, unsigned int src_indx, const unsigned char* prelocs, size_t reloc_count, Output_section*, - bool , + bool, size_t local_count, const unsigned char* plocal_syms) { - Object *dst_obj; - unsigned int dst_indx; + Scan scan; - typedef typename Reloc_types::Reloc Reltype; - const int reloc_size = Reloc_types::reloc_size; + typedef typename Classify_reloc::Reltype Reltype; + const int reloc_size = Classify_reloc::reloc_size; const int sym_size = elfcpp::Elf_sizes::sym_size; - std::vector* secvec = NULL; - std::vector* symvec = NULL; - std::vector >* addendvec = NULL; + Icf::Sections_reachable_info* secvec = NULL; + Icf::Symbol_info* symvec = NULL; + Icf::Addend_info* addendvec = NULL; + Icf::Offset_info* offsetvec = NULL; + Icf::Reloc_addend_size_info* reloc_addend_size_vec = NULL; bool is_icf_tracked = false; const char* cident_section_name = NULL; + std::string src_section_name = (parameters->options().icf_enabled() + ? src_obj->section_name(src_indx) + : ""); + + bool check_section_for_function_pointers = false; + if (parameters->options().icf_enabled() - && is_section_foldable_candidate(src_obj->section_name(src_indx).c_str())) + && is_section_foldable_candidate(src_section_name.c_str())) { is_icf_tracked = true; Section_id src_id(src_obj, src_indx); - secvec = &symtab->icf()->section_reloc_list()[src_id]; - symvec = &symtab->icf()->symbol_reloc_list()[src_id]; - addendvec = &symtab->icf()->addend_reloc_list()[src_id]; + Icf::Reloc_info* reloc_info = + &symtab->icf()->reloc_info_list()[src_id]; + secvec = &reloc_info->section_info; + symvec = &reloc_info->symbol_info; + addendvec = &reloc_info->addend_info; + offsetvec = &reloc_info->offset_info; + reloc_addend_size_vec = &reloc_info->reloc_addend_size_info; } + check_section_for_function_pointers = + symtab->icf()->check_section_for_function_pointers(src_section_name, + target); + for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size) { Reltype reloc(prelocs); - typename elfcpp::Elf_types::Elf_WXword r_info = reloc.get_r_info(); - unsigned int r_sym = elfcpp::elf_r_sym(r_info); + unsigned int r_sym = Classify_reloc::get_r_sym(&reloc); + unsigned int r_type = Classify_reloc::get_r_type(&reloc); typename elfcpp::Elf_types::Elf_Swxword addend = - Reloc_types::get_reloc_addend_noerror(&reloc); + Classify_reloc::get_r_addend(&reloc); + Relobj* dst_obj; + unsigned int dst_indx; + typedef typename elfcpp::Elf_types::Elf_Addr Address; + Address dst_off; if (r_sym < local_count) { gold_assert(plocal_syms != NULL); typename elfcpp::Sym lsym(plocal_syms + r_sym * sym_size); - unsigned int shndx = lsym.get_st_shndx(); + dst_indx = lsym.get_st_shndx(); bool is_ordinary; - shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary); - if (!is_ordinary) - continue; + dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary); dst_obj = src_obj; - dst_indx = shndx; - Section_id dst_id(dst_obj, dst_indx); + dst_off = lsym.get_st_value() + addend; + if (is_icf_tracked) { - (*secvec).push_back(dst_id); - (*symvec).push_back(NULL); - long long symvalue = static_cast(lsym.get_st_value()); - (*addendvec).push_back(std::make_pair(symvalue, - static_cast(addend))); + Address symvalue = dst_off - addend; + if (is_ordinary) + (*secvec).push_back(Section_id(src_obj, dst_indx)); + else + (*secvec).push_back(Section_id(NULL, 0)); + // If the target of the relocation is an STT_SECTION symbol, + // make a note of that by storing -1 in the symbol vector. + if (lsym.get_st_type() == elfcpp::STT_SECTION) + (*symvec).push_back(reinterpret_cast(-1)); + else + (*symvec).push_back(NULL); + (*addendvec).push_back(std::make_pair( + static_cast(symvalue), + static_cast(addend))); + uint64_t reloc_offset = + convert_to_section_size_type(reloc.get_r_offset()); + (*offsetvec).push_back(reloc_offset); + (*reloc_addend_size_vec).push_back( + get_embedded_addend_size(r_type, src_obj)); } - if (shndx == src_indx) + + // When doing safe folding, check to see if this relocation is that + // of a function pointer being taken. + if (is_ordinary + && check_section_for_function_pointers + && lsym.get_st_type() != elfcpp::STT_OBJECT + && scan.local_reloc_may_be_function_pointer(symtab, NULL, target, + src_obj, src_indx, + NULL, reloc, r_type, + lsym)) + symtab->icf()->set_section_has_function_pointers( + src_obj, lsym.get_st_shndx()); + + if (!is_ordinary || dst_indx == src_indx) continue; } else @@ -241,14 +284,31 @@ gc_process_relocs( gold_assert(gsym != NULL); if (gsym->is_forwarder()) gsym = symtab->resolve_forwards(gsym); - if (gsym->source() != Symbol::FROM_OBJECT) - continue; - bool is_ordinary; - dst_obj = gsym->object(); - dst_indx = gsym->shndx(&is_ordinary); - if (!is_ordinary) - continue; - Section_id dst_id(dst_obj, dst_indx); + + dst_obj = NULL; + dst_indx = 0; + bool is_ordinary = false; + if (gsym->source() == Symbol::FROM_OBJECT + && !gsym->object()->is_dynamic()) + { + dst_obj = static_cast(gsym->object()); + dst_indx = gsym->shndx(&is_ordinary); + } + dst_off = static_cast*>(gsym)->value(); + dst_off += addend; + + // When doing safe folding, check to see if this relocation is that + // of a function pointer being taken. + if (gsym->source() == Symbol::FROM_OBJECT + && gsym->type() == elfcpp::STT_FUNC + && check_section_for_function_pointers + && dst_obj != NULL + && (!is_ordinary + || scan.global_reloc_may_be_function_pointer( + symtab, NULL, target, src_obj, src_indx, NULL, reloc, + r_type, gsym))) + symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx); + // If the symbol name matches '__start_XXX' then the section with // the C identifier like name 'XXX' should not be garbage collected. // A similar treatment to symbols with the name '__stop_XXX'. @@ -264,19 +324,33 @@ gc_process_relocs( } if (is_icf_tracked) { - (*secvec).push_back(dst_id); + Address symvalue = dst_off - addend; + if (is_ordinary && dst_obj != NULL) + (*secvec).push_back(Section_id(dst_obj, dst_indx)); + else + (*secvec).push_back(Section_id(NULL, 0)); (*symvec).push_back(gsym); - Sized_symbol* sized_gsym = - static_cast* >(gsym); - long long symvalue = - static_cast(sized_gsym->value()); - (*addendvec).push_back(std::make_pair(symvalue, - static_cast(addend))); - } + (*addendvec).push_back(std::make_pair( + static_cast(symvalue), + static_cast(addend))); + uint64_t reloc_offset = + convert_to_section_size_type(reloc.get_r_offset()); + (*offsetvec).push_back(reloc_offset); + (*reloc_addend_size_vec).push_back( + get_embedded_addend_size(r_type, src_obj)); + } + + if (dst_obj == NULL) + continue; + if (!is_ordinary) + continue; } if (parameters->options().gc_sections()) { symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx); + parameters->sized_target() + ->gc_add_reference(symtab, src_obj, src_indx, dst_obj, dst_indx, + dst_off); if (cident_section_name != NULL) { Garbage_collection::Cident_section_map::iterator ele =