compressed_output.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. // compressed_output.cc -- manage compressed debug sections for gold
  2. // Copyright (C) 2007-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. #include "gold.h"
  18. #include <zlib.h>
  19. #include "parameters.h"
  20. #include "options.h"
  21. #include "compressed_output.h"
  22. namespace gold
  23. {
  24. // Compress UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns true
  25. // if it successfully compressed, false if it failed for any reason
  26. // (including not having zlib support in the library). If it returns
  27. // true, it allocates memory for the compressed data using new, and
  28. // sets *COMPRESSED_DATA and *COMPRESSED_SIZE to appropriate values.
  29. // It also writes a header before COMPRESSED_DATA: 4 bytes saying
  30. // "ZLIB", and 8 bytes indicating the uncompressed size, in big-endian
  31. // order.
  32. static bool
  33. zlib_compress(int header_size,
  34. const unsigned char* uncompressed_data,
  35. unsigned long uncompressed_size,
  36. unsigned char** compressed_data,
  37. unsigned long* compressed_size)
  38. {
  39. *compressed_size = uncompressed_size + uncompressed_size / 1000 + 128;
  40. *compressed_data = new unsigned char[*compressed_size + header_size];
  41. int compress_level;
  42. if (parameters->options().optimize() >= 1)
  43. compress_level = 9;
  44. else
  45. compress_level = 1;
  46. int rc = compress2(reinterpret_cast<Bytef*>(*compressed_data) + header_size,
  47. compressed_size,
  48. reinterpret_cast<const Bytef*>(uncompressed_data),
  49. uncompressed_size,
  50. compress_level);
  51. if (rc == Z_OK)
  52. {
  53. *compressed_size += header_size;
  54. return true;
  55. }
  56. else
  57. {
  58. delete[] *compressed_data;
  59. *compressed_data = NULL;
  60. return false;
  61. }
  62. }
  63. // Decompress COMPRESSED_DATA of size COMPRESSED_SIZE, into a buffer
  64. // UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns TRUE if it
  65. // decompressed successfully, false if it failed. The buffer, of
  66. // appropriate size, is provided by the caller, and is typically part
  67. // of the memory-mapped output file.
  68. static bool
  69. zlib_decompress(const unsigned char* compressed_data,
  70. unsigned long compressed_size,
  71. unsigned char* uncompressed_data,
  72. unsigned long uncompressed_size)
  73. {
  74. z_stream strm;
  75. int rc;
  76. /* It is possible the section consists of several compressed
  77. buffers concatenated together, so we uncompress in a loop. */
  78. strm.zalloc = NULL;
  79. strm.zfree = NULL;
  80. strm.opaque = NULL;
  81. strm.avail_in = compressed_size;
  82. strm.next_in = const_cast<Bytef*>(compressed_data);
  83. strm.avail_out = uncompressed_size;
  84. rc = inflateInit(&strm);
  85. while (strm.avail_in > 0)
  86. {
  87. if (rc != Z_OK)
  88. return false;
  89. strm.next_out = ((Bytef*) uncompressed_data
  90. + (uncompressed_size - strm.avail_out));
  91. rc = inflate(&strm, Z_FINISH);
  92. if (rc != Z_STREAM_END)
  93. return false;
  94. rc = inflateReset(&strm);
  95. }
  96. rc = inflateEnd(&strm);
  97. if (rc != Z_OK || strm.avail_out != 0)
  98. return false;
  99. return true;
  100. }
  101. // Read the compression header of a compressed debug section and return
  102. // the uncompressed size.
  103. uint64_t
  104. get_uncompressed_size(const unsigned char* compressed_data,
  105. section_size_type compressed_size)
  106. {
  107. const unsigned int zlib_header_size = 12;
  108. /* Verify the compression header. Currently, we support only zlib
  109. compression, so it should be "ZLIB" followed by the uncompressed
  110. section size, 8 bytes in big-endian order. */
  111. if (compressed_size >= zlib_header_size
  112. && strncmp(reinterpret_cast<const char*>(compressed_data),
  113. "ZLIB", 4) == 0)
  114. return elfcpp::Swap_unaligned<64, true>::readval(compressed_data + 4);
  115. return -1ULL;
  116. }
  117. // Decompress a compressed debug section directly into the output file.
  118. bool
  119. decompress_input_section(const unsigned char* compressed_data,
  120. unsigned long compressed_size,
  121. unsigned char* uncompressed_data,
  122. unsigned long uncompressed_size,
  123. int size,
  124. bool big_endian,
  125. elfcpp::Elf_Xword sh_flags)
  126. {
  127. if ((sh_flags & elfcpp::SHF_COMPRESSED) != 0)
  128. {
  129. unsigned int compression_header_size;
  130. if (size == 32)
  131. {
  132. compression_header_size = elfcpp::Elf_sizes<32>::chdr_size;
  133. if (big_endian)
  134. {
  135. elfcpp::Chdr<32, true> chdr(compressed_data);
  136. if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
  137. return false;
  138. }
  139. else
  140. {
  141. elfcpp::Chdr<32, false> chdr(compressed_data);
  142. if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
  143. return false;
  144. }
  145. }
  146. else if (size == 64)
  147. {
  148. compression_header_size = elfcpp::Elf_sizes<64>::chdr_size;
  149. if (big_endian)
  150. {
  151. elfcpp::Chdr<64, true> chdr(compressed_data);
  152. if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
  153. return false;
  154. }
  155. else
  156. {
  157. elfcpp::Chdr<64, false> chdr(compressed_data);
  158. if (chdr.get_ch_type() != elfcpp::ELFCOMPRESS_ZLIB)
  159. return false;
  160. }
  161. }
  162. else
  163. gold_unreachable();
  164. return zlib_decompress(compressed_data + compression_header_size,
  165. compressed_size - compression_header_size,
  166. uncompressed_data,
  167. uncompressed_size);
  168. }
  169. const unsigned int zlib_header_size = 12;
  170. /* Verify the compression header. Currently, we support only zlib
  171. compression, so it should be "ZLIB" followed by the uncompressed
  172. section size, 8 bytes in big-endian order. */
  173. if (compressed_size >= zlib_header_size
  174. && strncmp(reinterpret_cast<const char*>(compressed_data),
  175. "ZLIB", 4) == 0)
  176. {
  177. unsigned long uncompressed_size_check =
  178. elfcpp::Swap_unaligned<64, true>::readval(compressed_data + 4);
  179. gold_assert(uncompressed_size_check == uncompressed_size);
  180. return zlib_decompress(compressed_data + zlib_header_size,
  181. compressed_size - zlib_header_size,
  182. uncompressed_data,
  183. uncompressed_size);
  184. }
  185. return false;
  186. }
  187. // Class Output_compressed_section.
  188. // Set the final data size of a compressed section. This is where
  189. // we actually compress the section data.
  190. void
  191. Output_compressed_section::set_final_data_size()
  192. {
  193. off_t uncompressed_size = this->postprocessing_buffer_size();
  194. // (Try to) compress the data.
  195. unsigned long compressed_size;
  196. unsigned char* uncompressed_data = this->postprocessing_buffer();
  197. // At this point the contents of all regular input sections will
  198. // have been copied into the postprocessing buffer, and relocations
  199. // will have been applied. Now we need to copy in the contents of
  200. // anything other than a regular input section.
  201. this->write_to_postprocessing_buffer();
  202. bool success = false;
  203. enum { none, gnu_zlib, gabi_zlib } compress;
  204. int compression_header_size = 12;
  205. const int size = parameters->target().get_size();
  206. if (strcmp(this->options_->compress_debug_sections(), "zlib-gnu") == 0)
  207. compress = gnu_zlib;
  208. else if (strcmp(this->options_->compress_debug_sections(), "zlib-gabi") == 0
  209. || strcmp(this->options_->compress_debug_sections(), "zlib") == 0)
  210. {
  211. compress = gabi_zlib;
  212. if (size == 32)
  213. compression_header_size = elfcpp::Elf_sizes<32>::chdr_size;
  214. else if (size == 64)
  215. compression_header_size = elfcpp::Elf_sizes<64>::chdr_size;
  216. else
  217. gold_unreachable();
  218. }
  219. else
  220. compress = none;
  221. if (compress != none)
  222. success = zlib_compress(compression_header_size, uncompressed_data,
  223. uncompressed_size, &this->data_,
  224. &compressed_size);
  225. if (success)
  226. {
  227. elfcpp::Elf_Xword flags = this->flags();
  228. if (compress == gabi_zlib)
  229. {
  230. // Set the SHF_COMPRESSED bit.
  231. flags |= elfcpp::SHF_COMPRESSED;
  232. const bool is_big_endian = parameters->target().is_big_endian();
  233. uint64_t addralign = this->addralign();
  234. if (size == 32)
  235. {
  236. if (is_big_endian)
  237. {
  238. elfcpp::Chdr_write<32, true> chdr(this->data_);
  239. chdr.put_ch_type(elfcpp::ELFCOMPRESS_ZLIB);
  240. chdr.put_ch_size(uncompressed_size);
  241. chdr.put_ch_addralign(addralign);
  242. }
  243. else
  244. {
  245. elfcpp::Chdr_write<32, false> chdr(this->data_);
  246. chdr.put_ch_type(elfcpp::ELFCOMPRESS_ZLIB);
  247. chdr.put_ch_size(uncompressed_size);
  248. chdr.put_ch_addralign(addralign);
  249. }
  250. }
  251. else if (size == 64)
  252. {
  253. if (is_big_endian)
  254. {
  255. elfcpp::Chdr_write<64, true> chdr(this->data_);
  256. chdr.put_ch_type(elfcpp::ELFCOMPRESS_ZLIB);
  257. chdr.put_ch_size(uncompressed_size);
  258. chdr.put_ch_addralign(addralign);
  259. // Clear the reserved field.
  260. chdr.put_ch_reserved(0);
  261. }
  262. else
  263. {
  264. elfcpp::Chdr_write<64, false> chdr(this->data_);
  265. chdr.put_ch_type(elfcpp::ELFCOMPRESS_ZLIB);
  266. chdr.put_ch_size(uncompressed_size);
  267. chdr.put_ch_addralign(addralign);
  268. // Clear the reserved field.
  269. chdr.put_ch_reserved(0);
  270. }
  271. }
  272. else
  273. gold_unreachable();
  274. }
  275. else
  276. {
  277. // Write out the zlib header.
  278. memcpy(this->data_, "ZLIB", 4);
  279. elfcpp::Swap_unaligned<64, true>::writeval(this->data_ + 4,
  280. uncompressed_size);
  281. // This converts .debug_foo to .zdebug_foo
  282. this->new_section_name_ = std::string(".z") + (this->name() + 1);
  283. this->set_name(this->new_section_name_.c_str());
  284. }
  285. this->set_flags(flags);
  286. this->set_data_size(compressed_size);
  287. }
  288. else
  289. {
  290. gold_warning(_("not compressing section data: zlib error"));
  291. gold_assert(this->data_ == NULL);
  292. this->set_data_size(uncompressed_size);
  293. }
  294. }
  295. // Write out a compressed section. If we couldn't compress, we just
  296. // write it out as normal, uncompressed data.
  297. void
  298. Output_compressed_section::do_write(Output_file* of)
  299. {
  300. off_t offset = this->offset();
  301. off_t data_size = this->data_size();
  302. unsigned char* view = of->get_output_view(offset, data_size);
  303. if (this->data_ == NULL)
  304. memcpy(view, this->postprocessing_buffer(), data_size);
  305. else
  306. memcpy(view, this->data_, data_size);
  307. of->write_output_view(offset, data_size, view);
  308. }
  309. } // End namespace gold.