merge.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514
  1. // merge.h -- handle section merging for gold -*- C++ -*-
  2. // Copyright (C) 2006-2022 Free Software Foundation, Inc.
  3. // Written by Ian Lance Taylor <iant@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_MERGE_H
  18. #define GOLD_MERGE_H
  19. #include <climits>
  20. #include <map>
  21. #include <vector>
  22. #include "stringpool.h"
  23. #include "output.h"
  24. namespace gold
  25. {
  26. // For each object with merge sections, we store an Object_merge_map.
  27. // This is used to map locations in input sections to a merged output
  28. // section. The output section itself is not recorded here--it can be
  29. // found in the output_sections_ field of the Object.
  30. class Object_merge_map
  31. {
  32. public:
  33. Object_merge_map()
  34. : section_merge_maps_()
  35. { }
  36. ~Object_merge_map();
  37. // Add a mapping for MERGE_MAP, for the bytes from OFFSET to OFFSET
  38. // + LENGTH in the input section SHNDX to OUTPUT_OFFSET in the
  39. // output section. An OUTPUT_OFFSET of -1 means that the bytes are
  40. // discarded. OUTPUT_OFFSET is relative to the start of the merged
  41. // data in the output section.
  42. void
  43. add_mapping(const Output_section_data*, unsigned int shndx,
  44. section_offset_type offset, section_size_type length,
  45. section_offset_type output_offset);
  46. // Get the output offset for an input address. MERGE_MAP is the map
  47. // we are looking for, or NULL if we don't care. The input address
  48. // is at offset OFFSET in section SHNDX. This sets *OUTPUT_OFFSET
  49. // to the offset in the output section; this will be -1 if the bytes
  50. // are not being copied to the output. This returns true if the
  51. // mapping is known, false otherwise. *OUTPUT_OFFSET is relative to
  52. // the start of the merged data in the output section.
  53. bool
  54. get_output_offset(unsigned int shndx,
  55. section_offset_type offset,
  56. section_offset_type* output_offset);
  57. const Output_section_data*
  58. find_merge_section(unsigned int shndx) const;
  59. // Initialize an mapping from input offsets to output addresses for
  60. // section SHNDX. STARTING_ADDRESS is the output address of the
  61. // merged section.
  62. template<int size>
  63. void
  64. initialize_input_to_output_map(
  65. unsigned int shndx,
  66. typename elfcpp::Elf_types<size>::Elf_Addr starting_address,
  67. Unordered_map<section_offset_type,
  68. typename elfcpp::Elf_types<size>::Elf_Addr>*);
  69. // Map input section offsets to a length and an output section
  70. // offset. An output section offset of -1 means that this part of
  71. // the input section is being discarded.
  72. struct Input_merge_entry
  73. {
  74. // The offset in the input section.
  75. section_offset_type input_offset;
  76. // The length.
  77. section_size_type length;
  78. // The offset in the output section.
  79. section_offset_type output_offset;
  80. };
  81. // A list of entries for a particular input section.
  82. struct Input_merge_map
  83. {
  84. void add_mapping(section_offset_type input_offset, section_size_type length,
  85. section_offset_type output_offset);
  86. typedef std::vector<Input_merge_entry> Entries;
  87. // We store these with the Relobj, and we look them up by input
  88. // section. It is possible to have two different merge maps
  89. // associated with a single output section. For example, this
  90. // happens routinely with .rodata, when merged string constants
  91. // and merged fixed size constants are both put into .rodata. The
  92. // output offset that we store is not the offset from the start of
  93. // the output section; it is the offset from the start of the
  94. // merged data in the output section. That means that the caller
  95. // is going to add the offset of the merged data within the output
  96. // section, which means that the caller needs to know which set of
  97. // merged data it found the entry in. So it's not enough to find
  98. // this data based on the input section and the output section; we
  99. // also have to find it based on a set of merged data in the
  100. // output section. In order to verify that we are looking at the
  101. // right data, we store a pointer to the Merge_map here, and we
  102. // pass in a pointer when looking at the data. If we are asked to
  103. // look up information for a different Merge_map, we report that
  104. // we don't have it, rather than trying a lookup and returning an
  105. // answer which will receive the wrong offset.
  106. const Output_section_data* output_data;
  107. // The list of mappings.
  108. Entries entries;
  109. // Whether the ENTRIES field is sorted by input_offset.
  110. bool sorted;
  111. Input_merge_map()
  112. : output_data(NULL), entries(), sorted(true)
  113. { }
  114. };
  115. // Get or make the Input_merge_map to use for the section SHNDX
  116. // with MERGE_MAP.
  117. Input_merge_map*
  118. get_or_make_input_merge_map(const Output_section_data* merge_map,
  119. unsigned int shndx);
  120. private:
  121. // A less-than comparison routine for Input_merge_entry.
  122. struct Input_merge_compare
  123. {
  124. bool
  125. operator()(const Input_merge_entry& i1, const Input_merge_entry& i2) const
  126. { return i1.input_offset < i2.input_offset; }
  127. };
  128. // Map input section indices to merge maps.
  129. typedef std::vector<std::pair<unsigned int, Input_merge_map*> >
  130. Section_merge_maps;
  131. // Return a pointer to the Input_merge_map to use for the input
  132. // section SHNDX, or NULL.
  133. const Input_merge_map*
  134. get_input_merge_map(unsigned int shndx) const;
  135. Input_merge_map *
  136. get_input_merge_map(unsigned int shndx) {
  137. return const_cast<Input_merge_map *>(static_cast<const Object_merge_map *>(
  138. this)->get_input_merge_map(shndx));
  139. }
  140. Section_merge_maps section_merge_maps_;
  141. };
  142. // A general class for SHF_MERGE data, to hold functions shared by
  143. // fixed-size constant data and string data.
  144. class Output_merge_base : public Output_section_data
  145. {
  146. public:
  147. Output_merge_base(uint64_t entsize, uint64_t addralign)
  148. : Output_section_data(addralign), entsize_(entsize),
  149. keeps_input_sections_(false), first_relobj_(NULL), first_shndx_(-1),
  150. input_sections_()
  151. { }
  152. // Return the entry size.
  153. uint64_t
  154. entsize() const
  155. { return this->entsize_; }
  156. // Whether this is a merge string section. This is only true of
  157. // Output_merge_string.
  158. bool
  159. is_string()
  160. { return this->do_is_string(); }
  161. // Whether this keeps input sections.
  162. bool
  163. keeps_input_sections() const
  164. { return this->keeps_input_sections_; }
  165. // Set the keeps-input-sections flag. This is virtual so that sub-classes
  166. // can perform additional checks.
  167. void
  168. set_keeps_input_sections()
  169. { this->do_set_keeps_input_sections(); }
  170. // Return the object of the first merged input section. This used
  171. // for script processing. This is NULL if merge section is empty.
  172. Relobj*
  173. first_relobj() const
  174. { return this->first_relobj_; }
  175. // Return the section index of the first merged input section. This
  176. // is used for script processing. This is valid only if merge section
  177. // is not valid.
  178. unsigned int
  179. first_shndx() const
  180. {
  181. gold_assert(this->first_relobj_ != NULL);
  182. return this->first_shndx_;
  183. }
  184. // Set of merged input sections.
  185. typedef Unordered_set<Section_id, Section_id_hash> Input_sections;
  186. // Beginning of merged input sections.
  187. Input_sections::const_iterator
  188. input_sections_begin() const
  189. {
  190. gold_assert(this->keeps_input_sections_);
  191. return this->input_sections_.begin();
  192. }
  193. // Beginning of merged input sections.
  194. Input_sections::const_iterator
  195. input_sections_end() const
  196. {
  197. gold_assert(this->keeps_input_sections_);
  198. return this->input_sections_.end();
  199. }
  200. protected:
  201. // Return the output offset for an input offset.
  202. bool
  203. do_output_offset(const Relobj* object, unsigned int shndx,
  204. section_offset_type offset,
  205. section_offset_type* poutput) const;
  206. // This may be overridden by the child class.
  207. virtual bool
  208. do_is_string()
  209. { return false; }
  210. // This may be overridden by the child class.
  211. virtual void
  212. do_set_keeps_input_sections()
  213. { this->keeps_input_sections_ = true; }
  214. // Record the merged input section for script processing.
  215. void
  216. record_input_section(Relobj* relobj, unsigned int shndx);
  217. private:
  218. // The entry size. For fixed-size constants, this is the size of
  219. // the constants. For strings, this is the size of a character.
  220. uint64_t entsize_;
  221. // Whether we keep input sections.
  222. bool keeps_input_sections_;
  223. // Object of the first merged input section. We use this for script
  224. // processing.
  225. Relobj* first_relobj_;
  226. // Section index of the first merged input section.
  227. unsigned int first_shndx_;
  228. // Input sections. We only keep them is keeps_input_sections_ is true.
  229. Input_sections input_sections_;
  230. };
  231. // Handle SHF_MERGE sections with fixed-size constant data.
  232. class Output_merge_data : public Output_merge_base
  233. {
  234. public:
  235. Output_merge_data(uint64_t entsize, uint64_t addralign)
  236. : Output_merge_base(entsize, addralign), p_(NULL), len_(0), alc_(0),
  237. input_count_(0),
  238. hashtable_(128, Merge_data_hash(this), Merge_data_eq(this))
  239. { }
  240. protected:
  241. // Add an input section.
  242. bool
  243. do_add_input_section(Relobj* object, unsigned int shndx);
  244. // Set the final data size.
  245. void
  246. set_final_data_size();
  247. // Write the data to the file.
  248. void
  249. do_write(Output_file*);
  250. // Write the data to a buffer.
  251. void
  252. do_write_to_buffer(unsigned char*);
  253. // Write to a map file.
  254. void
  255. do_print_to_mapfile(Mapfile* mapfile) const
  256. { mapfile->print_output_data(this, _("** merge constants")); }
  257. // Print merge stats to stderr.
  258. void
  259. do_print_merge_stats(const char* section_name);
  260. // Set keeps-input-sections flag.
  261. void
  262. do_set_keeps_input_sections()
  263. {
  264. gold_assert(this->input_count_ == 0);
  265. Output_merge_base::do_set_keeps_input_sections();
  266. }
  267. private:
  268. // We build a hash table of the fixed-size constants. Each constant
  269. // is stored as a pointer into the section data we are accumulating.
  270. // A key in the hash table. This is an offset in the section
  271. // contents we are building.
  272. typedef section_offset_type Merge_data_key;
  273. // Compute the hash code. To do this we need a pointer back to the
  274. // object holding the data.
  275. class Merge_data_hash
  276. {
  277. public:
  278. Merge_data_hash(const Output_merge_data* pomd)
  279. : pomd_(pomd)
  280. { }
  281. size_t
  282. operator()(Merge_data_key) const;
  283. private:
  284. const Output_merge_data* pomd_;
  285. };
  286. friend class Merge_data_hash;
  287. // Compare two entries in the hash table for equality. To do this
  288. // we need a pointer back to the object holding the data. Note that
  289. // we now have a pointer to the object stored in two places in the
  290. // hash table. Fixing this would require specializing the hash
  291. // table, which would be hard to do portably.
  292. class Merge_data_eq
  293. {
  294. public:
  295. Merge_data_eq(const Output_merge_data* pomd)
  296. : pomd_(pomd)
  297. { }
  298. bool
  299. operator()(Merge_data_key k1, Merge_data_key k2) const;
  300. private:
  301. const Output_merge_data* pomd_;
  302. };
  303. friend class Merge_data_eq;
  304. // The type of the hash table.
  305. typedef Unordered_set<Merge_data_key, Merge_data_hash, Merge_data_eq>
  306. Merge_data_hashtable;
  307. // Given a hash table key, which is just an offset into the section
  308. // data, return a pointer to the corresponding constant.
  309. const unsigned char*
  310. constant(Merge_data_key k) const
  311. {
  312. gold_assert(k >= 0 && k < static_cast<section_offset_type>(this->len_));
  313. return this->p_ + k;
  314. }
  315. // Add a constant to the output.
  316. void
  317. add_constant(const unsigned char*);
  318. // The accumulated data.
  319. unsigned char* p_;
  320. // The length of the accumulated data.
  321. section_size_type len_;
  322. // The size of the allocated buffer.
  323. section_size_type alc_;
  324. // The number of entries seen in input files.
  325. size_t input_count_;
  326. // The hash table.
  327. Merge_data_hashtable hashtable_;
  328. };
  329. // Handle SHF_MERGE sections with string data. This is a template
  330. // based on the type of the characters in the string.
  331. template<typename Char_type>
  332. class Output_merge_string : public Output_merge_base
  333. {
  334. public:
  335. Output_merge_string(uint64_t addralign)
  336. : Output_merge_base(sizeof(Char_type), addralign), stringpool_(addralign),
  337. merged_strings_lists_(), input_count_(0), input_size_(0)
  338. {
  339. this->stringpool_.set_no_zero_null();
  340. }
  341. protected:
  342. // Add an input section.
  343. bool
  344. do_add_input_section(Relobj* object, unsigned int shndx);
  345. // Do all the final processing after the input sections are read in.
  346. // Returns the final data size.
  347. section_size_type
  348. finalize_merged_data();
  349. // Set the final data size.
  350. void
  351. set_final_data_size();
  352. // Write the data to the file.
  353. void
  354. do_write(Output_file*);
  355. // Write the data to a buffer.
  356. void
  357. do_write_to_buffer(unsigned char*);
  358. // Write to a map file.
  359. void
  360. do_print_to_mapfile(Mapfile* mapfile) const
  361. { mapfile->print_output_data(this, _("** merge strings")); }
  362. // Print merge stats to stderr.
  363. void
  364. do_print_merge_stats(const char* section_name);
  365. // Writes the stringpool to a buffer.
  366. void
  367. stringpool_to_buffer(unsigned char* buffer, section_size_type buffer_size)
  368. { this->stringpool_.write_to_buffer(buffer, buffer_size); }
  369. // Clears all the data in the stringpool, to save on memory.
  370. void
  371. clear_stringpool()
  372. { this->stringpool_.clear(); }
  373. // Whether this is a merge string section.
  374. virtual bool
  375. do_is_string()
  376. { return true; }
  377. // Set keeps-input-sections flag.
  378. void
  379. do_set_keeps_input_sections()
  380. {
  381. gold_assert(this->input_count_ == 0);
  382. Output_merge_base::do_set_keeps_input_sections();
  383. }
  384. private:
  385. // The name of the string type, for stats.
  386. const char*
  387. string_name();
  388. // As we see input sections, we build a mapping from object, section
  389. // index and offset to strings.
  390. struct Merged_string
  391. {
  392. // The offset in the input section.
  393. section_offset_type offset;
  394. // The key in the Stringpool.
  395. Stringpool::Key stringpool_key;
  396. Merged_string(section_offset_type offseta, Stringpool::Key stringpool_keya)
  397. : offset(offseta), stringpool_key(stringpool_keya)
  398. { }
  399. };
  400. typedef std::vector<Merged_string> Merged_strings;
  401. struct Merged_strings_list
  402. {
  403. // The input object where the strings were found.
  404. Relobj* object;
  405. // The input section in the input object.
  406. unsigned int shndx;
  407. // The list of merged strings.
  408. Merged_strings merged_strings;
  409. Merged_strings_list(Relobj* objecta, unsigned int shndxa)
  410. : object(objecta), shndx(shndxa), merged_strings()
  411. { }
  412. };
  413. typedef std::vector<Merged_strings_list*> Merged_strings_lists;
  414. // As we see the strings, we add them to a Stringpool.
  415. Stringpool_template<Char_type> stringpool_;
  416. // Map from a location in an input object to an entry in the
  417. // Stringpool.
  418. Merged_strings_lists merged_strings_lists_;
  419. // The number of entries seen in input files.
  420. size_t input_count_;
  421. // The total size of input sections.
  422. size_t input_size_;
  423. };
  424. } // End namespace gold.
  425. #endif // !defined(GOLD_MERGE_H)