* hostio.c: Correct copyright year.
[deliverable/binutils-gdb.git] / gold / compressed_output.cc
CommitLineData
9a0910c3
ILT
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
32namespace 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
b589a5bc
ILT
41#ifdef HAVE_ZLIB_H
42
9a0910c3
ILT
43static bool
44zlib_compress(const char* uncompressed_data, unsigned long uncompressed_size,
45 char** compressed_data, unsigned long* compressed_size)
46{
9a0910c3
ILT
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 }
9a0910c3
ILT
69}
70
b589a5bc
ILT
71#else // !defined(HAVE_ZLIB_H)
72
73static bool
74zlib_compress(const char*, unsigned long, char**, unsigned long*)
75{
76 return false;
77}
78
79#endif // !defined(HAVE_ZLIB_H)
80
9a0910c3
ILT
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
84static std::string
85zlib_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
96bool
97Output_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
107void
108Output_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
159const char*
160Output_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
173void
174Output_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
187template<typename Char_type>
188bool
189Output_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
198template<typename Char_type>
199void
200Output_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
233template<typename Char_type>
234const char*
235Output_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
248template<typename Char_type>
249void
250Output_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
266template
267class Output_compressed_string<char>;
268
269template
270class Output_compressed_string<uint16_t>;
271
272template
273class Output_compressed_string<uint32_t>;
274
275} // End namespace gold.
This page took 0.035313 seconds and 4 git commands to generate.