From Craig Silverstein: Add support for compressing .debug_str section.
[platform/upstream/binutils.git] / gold / compressed_output.cc
1 // compressed_output.cc -- manage compressed output sections for gold
2
3 // Copyright 2007 Free Software Foundation, Inc.
4 // Written by Ian Lance Taylor <iant@google.com>.
5
6 // This file is part of gold.
7
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 3 of the License, or
11 // (at your option) any later version.
12
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
21 // MA 02110-1301, USA.
22
23 #include "gold.h"
24
25 #ifdef HAVE_ZLIB_H
26 #include <zlib.h>
27 #endif
28
29 #include "compressed_output.h"
30 #include "parameters.h"
31
32 namespace gold
33 {
34
35 // Compress UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE.  Returns true
36 // if it successfully compressed, false if it failed for any reason
37 // (including not having zlib support in the library).  If it returns
38 // true, it allocates memory for the compressed data using new, and
39 // sets *COMPRESSED_DATA and *COMPRESSED_SIZE to appropriate values.
40
41 static bool
42 zlib_compress(const char* uncompressed_data, unsigned long uncompressed_size,
43               char** compressed_data, unsigned long* compressed_size)
44 {
45 #ifndef HAVE_ZLIB_H
46   return false;
47 #else
48   *compressed_size = uncompressed_size + uncompressed_size / 1000 + 128;
49   *compressed_data = new char[*compressed_size];
50
51   int compress_level;
52   if (parameters->optimization_level() >= 1)
53     compress_level = 9;
54   else
55     compress_level = 1;
56
57   int rc = compress2(reinterpret_cast<Bytef*>(*compressed_data),
58                      compressed_size,
59                      reinterpret_cast<const Bytef*>(uncompressed_data),
60                      uncompressed_size,
61                      compress_level);
62   if (rc == Z_OK)
63     return true;
64   else
65     {
66       delete[] *compressed_data;
67       *compressed_data = NULL;
68       return false;
69     }
70 #endif  // #ifdef HAVE_ZLIB_H
71 }
72
73 // After compressing an output section, we rename it from foo to
74 // foo.zlib.nnnn, where nnnn is the uncompressed size of the section.
75
76 static std::string
77 zlib_compressed_suffix(unsigned long uncompressed_size)
78 {
79   char size_string[64];
80   snprintf(size_string, sizeof(size_string), "%lu", uncompressed_size);
81   return std::string(".zlib.") + size_string;
82 }
83
84 // Class Output_compressed_section_data.
85
86 // Add an input section.  In this case, we just keep track of the sections.
87
88 bool
89 Output_compressed_section_data::do_add_input_section(Relobj* obj,
90                                                      unsigned int shndx)
91 {
92   this->objects_.push_back(Object_entry(obj, shndx));
93   return true;
94 }
95
96 // Set the final data size of a compressed section.  This is where
97 // we actually compress the section data.
98
99 void
100 Output_compressed_section_data::set_final_data_size()
101 {
102   // FIXME: assert that relocations have already been applied.
103
104   off_t uncompressed_size = 0;
105   for (std::vector<Object_entry>::iterator it = this->objects_.begin();
106        it != this->objects_.end();
107        ++it)
108     {
109       it->contents
110         = it->object->section_contents(it->shndx, &it->length, false);
111       uncompressed_size += it->length;
112     }
113
114   // (Try to) compress the data.
115   unsigned long compressed_size;
116   char* uncompressed_data = new char[uncompressed_size];
117   off_t pos = 0;
118   for (std::vector<Object_entry>::const_iterator it = this->objects_.begin();
119        it != this->objects_.end();
120        ++it)
121     {
122       memcpy(uncompressed_data + pos,
123              reinterpret_cast<const char*>(it->contents),
124              it->length);
125       pos += it->length;
126     }
127
128   bool success = false;
129   if (options_.zlib_compress_debug_sections())
130     success = zlib_compress(uncompressed_data, uncompressed_size,
131                             &this->data_, &compressed_size);
132   if (success)
133     {
134       delete[] uncompressed_data;
135       this->set_data_size(compressed_size);
136       this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
137     }
138   else
139     {
140       gold_warning(_("Not compressing section data: zlib error"));
141       gold_assert(this->data_ == NULL);
142       this->data_ = uncompressed_data;
143       this->set_data_size(uncompressed_size);
144     }
145 }
146
147 // Change the name of the output section to reflect it's compressed.
148 // The layout routines call into this right before finalizing the
149 // shstrtab.
150
151 const char*
152 Output_compressed_section_data::do_modified_output_section_name(
153   const char* name)
154 {
155   // This mean we never compressed the data.
156   if (this->new_section_name_.empty())
157     return NULL;
158   this->new_section_name_ = std::string(name) + this->new_section_name_;
159   return this->new_section_name_.c_str();
160 }
161
162 // Write out a compressed section.  If we couldn't compress, we just
163 // write it out as normal, uncompressed data.
164
165 void
166 Output_compressed_section_data::do_write(Output_file* of)
167 {
168   unsigned char* uview = of->get_output_view(this->offset(),
169                                              this->data_size());
170   char* view = reinterpret_cast<char*>(uview);
171   memcpy(view, this->data_, this->data_size());
172   of->write_output_view(this->offset(), this->data_size(), uview);
173 }
174
175 // Class Output_compressed_string.
176
177 // Add an input section.  We don't do anything special here.
178
179 template<typename Char_type>
180 bool
181 Output_compressed_string<Char_type>::do_add_input_section(Relobj* object,
182                                                           unsigned int shndx)
183 {
184   return Output_merge_string<Char_type>::do_add_input_section(object, shndx);
185 }
186
187 // Set the final data size of a compressed section.  This is where
188 // we actually compress the section data.
189
190 template<typename Char_type>
191 void
192 Output_compressed_string<Char_type>::set_final_data_size()
193 {
194   // First let the superclass finalize all its data, then write it to
195   // a buffer.
196   unsigned long uncompressed_size = this->finalize_merged_data();
197   char* uncompressed_data = new char[uncompressed_size];
198   this->stringpool_to_buffer(uncompressed_data, uncompressed_size);
199
200   // (Try to) compress the data.
201   unsigned long compressed_size;
202   if (options_.zlib_compress_debug_sections()
203       && zlib_compress(uncompressed_data, uncompressed_size,
204                        &this->compressed_data_, &compressed_size))
205     {
206       this->set_data_size(compressed_size);
207       // Save some memory.
208       this->clear_stringpool();
209       // We will be renaming the section to name.zlib.uncompressed_size.
210       this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
211     }
212   else
213     {
214       this->compressed_data_ = NULL;
215       this->set_data_size(uncompressed_size);
216     }
217
218   delete[] uncompressed_data;
219 }
220
221 // Change the name of the output section to reflect it's compressed.
222 // The layout routines call into this right before finalizing the
223 // shstrtab.
224
225 template<typename Char_type>
226 const char*
227 Output_compressed_string<Char_type>::do_modified_output_section_name(
228   const char* name)
229 {
230   // This mean we never compressed the data
231   if (this->new_section_name_.empty())
232     return NULL;
233   this->new_section_name_ = std::string(name) + this->new_section_name_;
234   return this->new_section_name_.c_str();
235 }
236
237 // Write out a compressed string section.  If we couldn't compress,
238 // we just write out the normal string section.
239
240 template<typename Char_type>
241 void
242 Output_compressed_string<Char_type>::do_write(Output_file* of)
243 {
244   if (this->compressed_data_ == NULL)
245     Output_merge_string<Char_type>::do_write(of);
246   else
247     {
248       unsigned char* uview = of->get_output_view(this->offset(),
249                                                  this->data_size());
250       char* view = reinterpret_cast<char*>(uview);
251       memcpy(view, this->compressed_data_, this->data_size());
252       of->write_output_view(this->offset(), this->data_size(), uview);
253     }
254 }
255
256 // Instantiate the templates we need.
257
258 template
259 class Output_compressed_string<char>;
260
261 template
262 class Output_compressed_string<uint16_t>;
263
264 template
265 class Output_compressed_string<uint32_t>;
266
267 } // End namespace gold.