gc.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. // gc.h -- garbage collection of unused sections
  2. // Copyright (C) 2009-2015 Free Software Foundation, Inc.
  3. // Written by Sriraman Tallam <tmsriram@google.com>.
  4. // This file is part of gold.
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 3 of the License, or
  8. // (at your option) any later version.
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
  16. // MA 02110-1301, USA.
  17. #ifndef GOLD_GC_H
  18. #define GOLD_GC_H
  19. #include <vector>
  20. #include "elfcpp.h"
  21. #include "symtab.h"
  22. #include "object.h"
  23. #include "icf.h"
  24. namespace gold
  25. {
  26. class Object;
  27. template<int size, bool big_endian>
  28. class Sized_relobj_file;
  29. template<int sh_type, int size, bool big_endian>
  30. struct Reloc_types;
  31. class Output_section;
  32. class General_options;
  33. class Layout;
  34. class Garbage_collection
  35. {
  36. public:
  37. typedef Unordered_set<Section_id, Section_id_hash> Sections_reachable;
  38. typedef std::map<Section_id, Sections_reachable> Section_ref;
  39. typedef std::vector<Section_id> Worklist_type;
  40. // This maps the name of the section which can be represented as a C
  41. // identifier (cident) to the list of sections that have that name.
  42. // Different object files can have cident sections with the same name.
  43. typedef std::map<std::string, Sections_reachable> Cident_section_map;
  44. Garbage_collection()
  45. : is_worklist_ready_(false)
  46. { }
  47. // Accessor methods for the private members.
  48. Sections_reachable&
  49. referenced_list()
  50. { return referenced_list_; }
  51. Section_ref&
  52. section_reloc_map()
  53. { return this->section_reloc_map_; }
  54. Worklist_type&
  55. worklist()
  56. { return this->work_list_; }
  57. bool
  58. is_worklist_ready()
  59. { return this->is_worklist_ready_; }
  60. void
  61. worklist_ready()
  62. { this->is_worklist_ready_ = true; }
  63. void
  64. do_transitive_closure();
  65. bool
  66. is_section_garbage(Relobj* obj, unsigned int shndx)
  67. { return (this->referenced_list().find(Section_id(obj, shndx))
  68. == this->referenced_list().end()); }
  69. Cident_section_map*
  70. cident_sections()
  71. { return &cident_sections_; }
  72. void
  73. add_cident_section(std::string section_name,
  74. Section_id secn)
  75. { this->cident_sections_[section_name].insert(secn); }
  76. // Add a reference from the SRC_SHNDX-th section of SRC_OBJECT to
  77. // DST_SHNDX-th section of DST_OBJECT.
  78. void
  79. add_reference(Relobj* src_object, unsigned int src_shndx,
  80. Relobj* dst_object, unsigned int dst_shndx)
  81. {
  82. Section_id src_id(src_object, src_shndx);
  83. Section_id dst_id(dst_object, dst_shndx);
  84. Sections_reachable& reachable = this->section_reloc_map_[src_id];
  85. reachable.insert(dst_id);
  86. }
  87. private:
  88. Worklist_type work_list_;
  89. bool is_worklist_ready_;
  90. Section_ref section_reloc_map_;
  91. Sections_reachable referenced_list_;
  92. Cident_section_map cident_sections_;
  93. };
  94. // Data to pass between successive invocations of do_layout
  95. // in object.cc while garbage collecting. This data structure
  96. // is filled by using the data from Read_symbols_data.
  97. struct Symbols_data
  98. {
  99. // Section headers.
  100. unsigned char* section_headers_data;
  101. // Section names.
  102. unsigned char* section_names_data;
  103. // Size of section name data in bytes.
  104. section_size_type section_names_size;
  105. // Symbol data.
  106. unsigned char* symbols_data;
  107. // Size of symbol data in bytes.
  108. section_size_type symbols_size;
  109. // Offset of external symbols within symbol data. This structure
  110. // sometimes contains only external symbols, in which case this will
  111. // be zero. Sometimes it contains all symbols.
  112. section_offset_type external_symbols_offset;
  113. // Symbol names.
  114. unsigned char* symbol_names_data;
  115. // Size of symbol name data in bytes.
  116. section_size_type symbol_names_size;
  117. };
  118. // Relocations of type SHT_REL store the addend value in their bytes.
  119. // This function returns the size of the embedded addend which is
  120. // nothing but the size of the relocation.
  121. template<typename Classify_reloc>
  122. inline unsigned int
  123. get_embedded_addend_size(int sh_type, int r_type, Relobj* obj)
  124. {
  125. if (sh_type != elfcpp::SHT_REL)
  126. return 0;
  127. Classify_reloc classify_reloc;
  128. return classify_reloc.get_size_for_reloc(r_type, obj);
  129. }
  130. // This function implements the generic part of reloc
  131. // processing to map a section to all the sections it
  132. // references through relocs. It is called only during
  133. // garbage collection (--gc-sections) and identical code
  134. // folding (--icf).
  135. template<int size, bool big_endian, typename Target_type, int sh_type,
  136. typename Scan, typename Classify_reloc>
  137. inline void
  138. gc_process_relocs(
  139. Symbol_table* symtab,
  140. Layout*,
  141. Target_type* target,
  142. Sized_relobj_file<size, big_endian>* src_obj,
  143. unsigned int src_indx,
  144. const unsigned char* prelocs,
  145. size_t reloc_count,
  146. Output_section*,
  147. bool,
  148. size_t local_count,
  149. const unsigned char* plocal_syms)
  150. {
  151. Scan scan;
  152. typedef typename Reloc_types<sh_type, size, big_endian>::Reloc Reltype;
  153. const int reloc_size = Reloc_types<sh_type, size, big_endian>::reloc_size;
  154. const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
  155. Icf::Sections_reachable_info* secvec = NULL;
  156. Icf::Symbol_info* symvec = NULL;
  157. Icf::Addend_info* addendvec = NULL;
  158. Icf::Offset_info* offsetvec = NULL;
  159. Icf::Reloc_addend_size_info* reloc_addend_size_vec = NULL;
  160. bool is_icf_tracked = false;
  161. const char* cident_section_name = NULL;
  162. std::string src_section_name = (parameters->options().icf_enabled()
  163. ? src_obj->section_name(src_indx)
  164. : "");
  165. bool check_section_for_function_pointers = false;
  166. if (parameters->options().icf_enabled()
  167. && is_section_foldable_candidate(src_section_name.c_str()))
  168. {
  169. is_icf_tracked = true;
  170. Section_id src_id(src_obj, src_indx);
  171. Icf::Reloc_info* reloc_info =
  172. &symtab->icf()->reloc_info_list()[src_id];
  173. secvec = &reloc_info->section_info;
  174. symvec = &reloc_info->symbol_info;
  175. addendvec = &reloc_info->addend_info;
  176. offsetvec = &reloc_info->offset_info;
  177. reloc_addend_size_vec = &reloc_info->reloc_addend_size_info;
  178. }
  179. check_section_for_function_pointers =
  180. symtab->icf()->check_section_for_function_pointers(src_section_name,
  181. target);
  182. for (size_t i = 0; i < reloc_count; ++i, prelocs += reloc_size)
  183. {
  184. Reltype reloc(prelocs);
  185. typename elfcpp::Elf_types<size>::Elf_WXword r_info = reloc.get_r_info();
  186. unsigned int r_sym = elfcpp::elf_r_sym<size>(r_info);
  187. unsigned int r_type = elfcpp::elf_r_type<size>(r_info);
  188. typename elfcpp::Elf_types<size>::Elf_Swxword addend =
  189. Reloc_types<sh_type, size, big_endian>::get_reloc_addend_noerror(&reloc);
  190. Relobj* dst_obj;
  191. unsigned int dst_indx;
  192. typedef typename elfcpp::Elf_types<size>::Elf_Addr Address;
  193. Address dst_off;
  194. if (r_sym < local_count)
  195. {
  196. gold_assert(plocal_syms != NULL);
  197. typename elfcpp::Sym<size, big_endian> lsym(plocal_syms
  198. + r_sym * sym_size);
  199. dst_indx = lsym.get_st_shndx();
  200. bool is_ordinary;
  201. dst_indx = src_obj->adjust_sym_shndx(r_sym, dst_indx, &is_ordinary);
  202. dst_obj = src_obj;
  203. dst_off = lsym.get_st_value() + addend;
  204. if (is_icf_tracked)
  205. {
  206. Address symvalue = dst_off - addend;
  207. if (is_ordinary)
  208. (*secvec).push_back(Section_id(src_obj, dst_indx));
  209. else
  210. (*secvec).push_back(Section_id(NULL, 0));
  211. (*symvec).push_back(NULL);
  212. (*addendvec).push_back(std::make_pair(
  213. static_cast<long long>(symvalue),
  214. static_cast<long long>(addend)));
  215. uint64_t reloc_offset =
  216. convert_to_section_size_type(reloc.get_r_offset());
  217. (*offsetvec).push_back(reloc_offset);
  218. (*reloc_addend_size_vec).push_back(
  219. get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
  220. src_obj));
  221. }
  222. // When doing safe folding, check to see if this relocation is that
  223. // of a function pointer being taken.
  224. if (is_ordinary
  225. && check_section_for_function_pointers
  226. && lsym.get_st_type() != elfcpp::STT_OBJECT
  227. && scan.local_reloc_may_be_function_pointer(symtab, NULL, NULL,
  228. src_obj, src_indx,
  229. NULL, reloc, r_type,
  230. lsym))
  231. symtab->icf()->set_section_has_function_pointers(
  232. src_obj, lsym.get_st_shndx());
  233. if (!is_ordinary || dst_indx == src_indx)
  234. continue;
  235. }
  236. else
  237. {
  238. Symbol* gsym = src_obj->global_symbol(r_sym);
  239. gold_assert(gsym != NULL);
  240. if (gsym->is_forwarder())
  241. gsym = symtab->resolve_forwards(gsym);
  242. dst_obj = NULL;
  243. dst_indx = 0;
  244. bool is_ordinary = false;
  245. if (gsym->source() == Symbol::FROM_OBJECT
  246. && !gsym->object()->is_dynamic())
  247. {
  248. dst_obj = static_cast<Relobj*>(gsym->object());
  249. dst_indx = gsym->shndx(&is_ordinary);
  250. }
  251. dst_off = static_cast<const Sized_symbol<size>*>(gsym)->value();
  252. dst_off += addend;
  253. // When doing safe folding, check to see if this relocation is that
  254. // of a function pointer being taken.
  255. if (gsym->source() == Symbol::FROM_OBJECT
  256. && check_section_for_function_pointers
  257. && dst_obj != NULL
  258. && (!is_ordinary
  259. || scan.global_reloc_may_be_function_pointer(
  260. symtab, NULL, NULL, src_obj, src_indx, NULL, reloc,
  261. r_type, gsym)))
  262. symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx);
  263. // If the symbol name matches '__start_XXX' then the section with
  264. // the C identifier like name 'XXX' should not be garbage collected.
  265. // A similar treatment to symbols with the name '__stop_XXX'.
  266. if (is_prefix_of(cident_section_start_prefix, gsym->name()))
  267. {
  268. cident_section_name = (gsym->name()
  269. + strlen(cident_section_start_prefix));
  270. }
  271. else if (is_prefix_of(cident_section_stop_prefix, gsym->name()))
  272. {
  273. cident_section_name = (gsym->name()
  274. + strlen(cident_section_stop_prefix));
  275. }
  276. if (is_icf_tracked)
  277. {
  278. Address symvalue = dst_off - addend;
  279. if (is_ordinary && dst_obj != NULL)
  280. (*secvec).push_back(Section_id(dst_obj, dst_indx));
  281. else
  282. (*secvec).push_back(Section_id(NULL, 0));
  283. (*symvec).push_back(gsym);
  284. (*addendvec).push_back(std::make_pair(
  285. static_cast<long long>(symvalue),
  286. static_cast<long long>(addend)));
  287. uint64_t reloc_offset =
  288. convert_to_section_size_type(reloc.get_r_offset());
  289. (*offsetvec).push_back(reloc_offset);
  290. (*reloc_addend_size_vec).push_back(
  291. get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
  292. src_obj));
  293. }
  294. if (dst_obj == NULL)
  295. continue;
  296. if (!is_ordinary)
  297. continue;
  298. }
  299. if (parameters->options().gc_sections())
  300. {
  301. symtab->gc()->add_reference(src_obj, src_indx, dst_obj, dst_indx);
  302. parameters->sized_target<size, big_endian>()
  303. ->gc_add_reference(symtab, src_obj, src_indx, dst_obj, dst_indx,
  304. dst_off);
  305. if (cident_section_name != NULL)
  306. {
  307. Garbage_collection::Cident_section_map::iterator ele =
  308. symtab->gc()->cident_sections()->find(std::string(cident_section_name));
  309. if (ele == symtab->gc()->cident_sections()->end())
  310. continue;
  311. Section_id src_id(src_obj, src_indx);
  312. Garbage_collection::Sections_reachable&
  313. v(symtab->gc()->section_reloc_map()[src_id]);
  314. Garbage_collection::Sections_reachable& cident_secn(ele->second);
  315. for (Garbage_collection::Sections_reachable::iterator it_v
  316. = cident_secn.begin();
  317. it_v != cident_secn.end();
  318. ++it_v)
  319. {
  320. v.insert(*it_v);
  321. }
  322. }
  323. }
  324. }
  325. return;
  326. }
  327. } // End of namespace gold.
  328. #endif