From Cary Coutant: Avoid compilation warnings if no zlib.h.
[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 #ifdef HAVE_ZLIB_H
42
43 static bool
44 zlib_compress(const char* uncompressed_data, unsigned long uncompressed_size,
45               char** compressed_data, unsigned long* compressed_size)
46 {
47   *compressed_size = uncompressed_size + uncompressed_size / 1000 + 128;
48   *compressed_data = new char[*compressed_size];
49
50   int compress_level;
51   if (parameters->optimization_level() >= 1)
52     compress_level = 9;
53   else
54     compress_level = 1;
55
56   int rc = compress2(reinterpret_cast<Bytef*>(*compressed_data),
57                      compressed_size,
58                      reinterpret_cast<const Bytef*>(uncompressed_data),
59                      uncompressed_size,
60                      compress_level);
61   if (rc == Z_OK)
62     return true;
63   else
64     {
65       delete[] *compressed_data;
66       *compressed_data = NULL;
67       return false;
68     }
69 }
70
71 #else // !defined(HAVE_ZLIB_H)
72
73 static bool
74 zlib_compress(const char*, unsigned long, char**, unsigned long*)
75 {
76   return false;
77 }
78
79 #endif // !defined(HAVE_ZLIB_H)
80
81 // After compressing an output section, we rename it from foo to
82 // foo.zlib.nnnn, where nnnn is the uncompressed size of the section.
83
84 static std::string
85 zlib_compressed_suffix(unsigned long uncompressed_size)
86 {
87   char size_string[64];
88   snprintf(size_string, sizeof(size_string), "%lu", uncompressed_size);
89   return std::string(".zlib.") + size_string;
90 }
91
92 // Class Output_compressed_section_data.
93
94 // Add an input section.  In this case, we just keep track of the sections.
95
96 bool
97 Output_compressed_section_data::do_add_input_section(Relobj* obj,
98                                                      unsigned int shndx)
99 {
100   this->objects_.push_back(Object_entry(obj, shndx));
101   return true;
102 }
103
104 // Set the final data size of a compressed section.  This is where
105 // we actually compress the section data.
106
107 void
108 Output_compressed_section_data::set_final_data_size()
109 {
110   // FIXME: assert that relocations have already been applied.
111
112   off_t uncompressed_size = 0;
113   for (std::vector<Object_entry>::iterator it = this->objects_.begin();
114        it != this->objects_.end();
115        ++it)
116     {
117       it->contents
118         = it->object->section_contents(it->shndx, &it->length, false);
119       uncompressed_size += it->length;
120     }
121
122   // (Try to) compress the data.
123   unsigned long compressed_size;
124   char* uncompressed_data = new char[uncompressed_size];
125   off_t pos = 0;
126   for (std::vector<Object_entry>::const_iterator it = this->objects_.begin();
127        it != this->objects_.end();
128        ++it)
129     {
130       memcpy(uncompressed_data + pos,
131              reinterpret_cast<const char*>(it->contents),
132              it->length);
133       pos += it->length;
134     }
135
136   bool success = false;
137   if (options_.zlib_compress_debug_sections())
138     success = zlib_compress(uncompressed_data, uncompressed_size,
139                             &this->data_, &compressed_size);
140   if (success)
141     {
142       delete[] uncompressed_data;
143       this->set_data_size(compressed_size);
144       this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
145     }
146   else
147     {
148       gold_warning(_("Not compressing section data: zlib error"));
149       gold_assert(this->data_ == NULL);
150       this->data_ = uncompressed_data;
151       this->set_data_size(uncompressed_size);
152     }
153 }
154
155 // Change the name of the output section to reflect it's compressed.
156 // The layout routines call into this right before finalizing the
157 // shstrtab.
158
159 const char*
160 Output_compressed_section_data::do_modified_output_section_name(
161   const char* name)
162 {
163   // This mean we never compressed the data.
164   if (this->new_section_name_.empty())
165     return NULL;
166   this->new_section_name_ = std::string(name) + this->new_section_name_;
167   return this->new_section_name_.c_str();
168 }
169
170 // Write out a compressed section.  If we couldn't compress, we just
171 // write it out as normal, uncompressed data.
172
173 void
174 Output_compressed_section_data::do_write(Output_file* of)
175 {
176   unsigned char* uview = of->get_output_view(this->offset(),
177                                              this->data_size());
178   char* view = reinterpret_cast<char*>(uview);
179   memcpy(view, this->data_, this->data_size());
180   of->write_output_view(this->offset(), this->data_size(), uview);
181 }
182
183 // Class Output_compressed_string.
184
185 // Add an input section.  We don't do anything special here.
186
187 template<typename Char_type>
188 bool
189 Output_compressed_string<Char_type>::do_add_input_section(Relobj* object,
190                                                           unsigned int shndx)
191 {
192   return Output_merge_string<Char_type>::do_add_input_section(object, shndx);
193 }
194
195 // Set the final data size of a compressed section.  This is where
196 // we actually compress the section data.
197
198 template<typename Char_type>
199 void
200 Output_compressed_string<Char_type>::set_final_data_size()
201 {
202   // First let the superclass finalize all its data, then write it to
203   // a buffer.
204   unsigned long uncompressed_size = this->finalize_merged_data();
205   char* uncompressed_data = new char[uncompressed_size];
206   this->stringpool_to_buffer(uncompressed_data, uncompressed_size);
207
208   // (Try to) compress the data.
209   unsigned long compressed_size;
210   if (options_.zlib_compress_debug_sections()
211       && zlib_compress(uncompressed_data, uncompressed_size,
212                        &this->compressed_data_, &compressed_size))
213     {
214       this->set_data_size(compressed_size);
215       // Save some memory.
216       this->clear_stringpool();
217       // We will be renaming the section to name.zlib.uncompressed_size.
218       this->new_section_name_ = zlib_compressed_suffix(uncompressed_size);
219     }
220   else
221     {
222       this->compressed_data_ = NULL;
223       this->set_data_size(uncompressed_size);
224     }
225
226   delete[] uncompressed_data;
227 }
228
229 // Change the name of the output section to reflect it's compressed.
230 // The layout routines call into this right before finalizing the
231 // shstrtab.
232
233 template<typename Char_type>
234 const char*
235 Output_compressed_string<Char_type>::do_modified_output_section_name(
236   const char* name)
237 {
238   // This mean we never compressed the data
239   if (this->new_section_name_.empty())
240     return NULL;
241   this->new_section_name_ = std::string(name) + this->new_section_name_;
242   return this->new_section_name_.c_str();
243 }
244
245 // Write out a compressed string section.  If we couldn't compress,
246 // we just write out the normal string section.
247
248 template<typename Char_type>
249 void
250 Output_compressed_string<Char_type>::do_write(Output_file* of)
251 {
252   if (this->compressed_data_ == NULL)
253     Output_merge_string<Char_type>::do_write(of);
254   else
255     {
256       unsigned char* uview = of->get_output_view(this->offset(),
257                                                  this->data_size());
258       char* view = reinterpret_cast<char*>(uview);
259       memcpy(view, this->compressed_data_, this->data_size());
260       of->write_output_view(this->offset(), this->data_size(), uview);
261     }
262 }
263
264 // Instantiate the templates we need.
265
266 template
267 class Output_compressed_string<char>;
268
269 template
270 class Output_compressed_string<uint16_t>;
271
272 template
273 class Output_compressed_string<uint32_t>;
274
275 } // End namespace gold.