1// reduced_debug_output.cc -- output reduced debugging information to save space
2
3// Copyright (C) 2008-2017 Free Software Foundation, Inc.
4// Written by Caleb Howe <cshowe@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#include "parameters.h"
26#include "options.h"
27#include "dwarf.h"
28#include "dwarf_reader.h"
29#include "reduced_debug_output.h"
30#include "int_encoding.h"
31
32#include <vector>
33
34namespace gold
35{
36
37// Given a pointer to the beginning of a die and the beginning of the associated
38// abbreviation fills in die_end with the end of the information entry.  If
39// successful returns true.  Get_die_end also takes a pointer to the end of the
40// buffer containing the die.  If die_end would be beyond the end of the
41// buffer, or if an unsupported dwarf form is encountered returns false.
42bool
43Output_reduced_debug_info_section::get_die_end(
44    unsigned char* die, unsigned char* abbrev, unsigned char** die_end,
45    unsigned char* buffer_end, int address_size, bool is64)
46{
47  size_t LEB_size;
48  uint64_t LEB_decoded;
49  for(;;)
50    {
51      uint64_t attribute = read_unsigned_LEB_128(abbrev, &LEB_size);
52      abbrev += LEB_size;
53      elfcpp::DW_FORM form =
54          static_cast<elfcpp::DW_FORM>(read_unsigned_LEB_128(abbrev,
55                                                             &LEB_size));
56      abbrev += LEB_size;
57      if (!(attribute || form))
58        break;
59      if (die >= buffer_end)
60        return false;
61      switch(form)
62        {
63          case elfcpp::DW_FORM_flag_present:
64            break;
65          case elfcpp::DW_FORM_strp:
66          case elfcpp::DW_FORM_sec_offset:
67            die += is64 ? 8 : 4;
68            break;
69          case elfcpp::DW_FORM_addr:
70          case elfcpp::DW_FORM_ref_addr:
71            die += address_size;
72            break;
73          case elfcpp::DW_FORM_block1:
74            die += *die;
75            die += 1;
76            break;
77          case elfcpp::DW_FORM_block2:
78            {
79              uint16_t block_size;
80              block_size = read_from_pointer<16>(&die);
81              die += block_size;
82              break;
83            }
84          case elfcpp::DW_FORM_block4:
85            {
86              uint32_t block_size;
87              block_size = read_from_pointer<32>(&die);
88              die += block_size;
89              break;
90            }
91          case elfcpp::DW_FORM_block:
92          case elfcpp::DW_FORM_exprloc:
93            LEB_decoded = read_unsigned_LEB_128(die, &LEB_size);
94            die += (LEB_decoded + LEB_size);
95            break;
96          case elfcpp::DW_FORM_data1:
97          case elfcpp::DW_FORM_ref1:
98          case elfcpp::DW_FORM_flag:
99            die += 1;
100            break;
101          case elfcpp::DW_FORM_data2:
102          case elfcpp::DW_FORM_ref2:
103            die += 2;
104            break;
105          case elfcpp::DW_FORM_data4:
106          case elfcpp::DW_FORM_ref4:
107            die += 4;
108            break;
109          case elfcpp::DW_FORM_data8:
110          case elfcpp::DW_FORM_ref8:
111          case elfcpp::DW_FORM_ref_sig8:
112            die += 8;
113            break;
114          case elfcpp::DW_FORM_ref_udata:
115          case elfcpp::DW_FORM_udata:
116            read_unsigned_LEB_128(die, &LEB_size);
117            die += LEB_size;
118            break;
119          case elfcpp::DW_FORM_sdata:
120            read_signed_LEB_128(die, &LEB_size);
121            die += LEB_size;
122            break;
123          case elfcpp::DW_FORM_string:
124            {
125              size_t length = strlen(reinterpret_cast<char*>(die));
126              die += length + 1;
127              break;
128            }
129          case elfcpp::DW_FORM_indirect:
130          case elfcpp::DW_FORM_GNU_addr_index:
131          case elfcpp::DW_FORM_GNU_str_index:
132          default:
133            return false;
134      }
135    }
136  *die_end = die;
137  return true;
138}
139
140void
141Output_reduced_debug_abbrev_section::set_final_data_size()
142{
143  if (this->sized_ || this->failed_)
144    return;
145
146  uint64_t abbrev_number;
147  size_t LEB_size;
148  unsigned char* abbrev_data = this->postprocessing_buffer();
149  unsigned char* abbrev_end = this->postprocessing_buffer() +
150                              this->postprocessing_buffer_size();
151  this->write_to_postprocessing_buffer();
152  while(abbrev_data < abbrev_end)
153    {
154      uint64_t abbrev_offset = abbrev_data - this->postprocessing_buffer();
155      while((abbrev_number = read_unsigned_LEB_128(abbrev_data, &LEB_size)))
156        {
157          if (abbrev_data >= abbrev_end)
158            {
159              failed("Debug abbreviations extend beyond .debug_abbrev "
160                     "section; failed to reduce debug abbreviations");
161              return;
162            }
163          abbrev_data += LEB_size;
164
165          // Together with the abbreviation number these fields make up
166          // the header for each abbreviation.
167          uint64_t abbrev_type = read_unsigned_LEB_128(abbrev_data, &LEB_size);
168          abbrev_data += LEB_size;
169
170          // This would ordinarily be the has_children field of the
171          // abbreviation.  But it's going to be false after reducing the
172          // information, so there's no point in storing it.
173          abbrev_data++;
174
175          // Read to the end of the current abbreviation.
176          // This is indicated by two zero unsigned LEBs in a row.  We don't
177          // need to parse the data yet, so we just scan through the data
178          // looking for two consecutive 0 bytes indicating the end of the
179          // abbreviation.
180          unsigned char* current_abbrev;
181          for (current_abbrev = abbrev_data;
182               current_abbrev[0] || current_abbrev[1];
183               current_abbrev++)
184            {
185              if (current_abbrev >= abbrev_end)
186                {
187                  this->failed(_("Debug abbreviations extend beyond "
188				 ".debug_abbrev section; failed to reduce "
189				 "debug abbreviations"));
190                  return;
191                }
192            }
193          // Account for the two nulls and advance to the start of the
194          // next abbreviation.
195          current_abbrev += 2;
196
197          // We're eliminating every entry except for compile units, so we
198          // only need to store abbreviations that describe them
199          if (abbrev_type == elfcpp::DW_TAG_compile_unit)
200            {
201              write_unsigned_LEB_128(&this->data_, ++this->abbrev_count_);
202              write_unsigned_LEB_128(&this->data_, abbrev_type);
203              // has_children is false for all entries
204              this->data_.push_back(0);
205              this->abbrev_mapping_[std::make_pair(abbrev_offset,
206                                                   abbrev_number)] =
207                  std::make_pair(abbrev_count_, this->data_.size());
208              this->data_.insert(this->data_.end(), abbrev_data,
209                                 current_abbrev);
210            }
211          abbrev_data = current_abbrev;
212        }
213      gold_assert(LEB_size == 1);
214      abbrev_data += LEB_size;
215    }
216  // Null terminate the list of abbreviations
217  this->data_.push_back(0);
218  this->set_data_size(data_.size());
219  this->sized_ = true;
220}
221
222void
223Output_reduced_debug_abbrev_section::do_write(Output_file* of)
224{
225  off_t offset = this->offset();
226  off_t data_size = this->data_size();
227  unsigned char* view = of->get_output_view(offset, data_size);
228  if (this->failed_)
229    memcpy(view, this->postprocessing_buffer(),
230           this->postprocessing_buffer_size());
231  else
232    memcpy(view, &this->data_.front(), data_size);
233  of->write_output_view(offset, data_size, view);
234}
235
236// Locates the abbreviation with abbreviation_number abbrev_number in the
237// abbreviation table at offset abbrev_offset.  abbrev_number is updated with
238// its new abbreviation number and a pointer to the beginning of the
239// abbreviation is returned.
240unsigned char*
241Output_reduced_debug_abbrev_section::get_new_abbrev(
242  uint64_t* abbrev_number, uint64_t abbrev_offset)
243{
244  set_final_data_size();
245  std::pair<uint64_t, uint64_t> abbrev_info =
246      this->abbrev_mapping_[std::make_pair(abbrev_offset, *abbrev_number)];
247  *abbrev_number = abbrev_info.first;
248  return &this->data_[abbrev_info.second];
249}
250
251void Output_reduced_debug_info_section::set_final_data_size()
252{
253  if (this->failed_)
254    return;
255  unsigned char* debug_info = this->postprocessing_buffer();
256  unsigned char* debug_info_end = (this->postprocessing_buffer()
257				   + this->postprocessing_buffer_size());
258  unsigned char* next_compile_unit;
259  this->write_to_postprocessing_buffer();
260
261  while (debug_info < debug_info_end)
262    {
263      uint32_t compile_unit_start = read_from_pointer<32>(&debug_info);
264      // The first 4 bytes of each compile unit determine whether or
265      // not we're using dwarf32 or dwarf64.  This is not necessarily
266      // related to whether the binary is 32 or 64 bits.
267      if (compile_unit_start == 0xFFFFFFFF)
268        {
269          // Technically the size can be up to 96 bits.  Rather than handle
270          // 96/128 bit integers we just truncate the size at 64 bits.
271          if (0 != read_from_pointer<32>(&debug_info))
272            {
273              this->failed(_("Extremely large compile unit in debug info; "
274			     "failed to reduce debug info"));
275              return;
276            }
277          const int dwarf64_header_size = sizeof(uint64_t) + sizeof(uint16_t) +
278                                          sizeof(uint64_t) + sizeof(uint8_t);
279          if (debug_info + dwarf64_header_size >= debug_info_end)
280            {
281              this->failed(_("Debug info extends beyond .debug_info section;"
282			     "failed to reduce debug info"));
283              return;
284            }
285
286          uint64_t compile_unit_size = read_from_pointer<64>(&debug_info);
287          next_compile_unit = debug_info + compile_unit_size;
288          uint16_t version = read_from_pointer<16>(&debug_info);
289          uint64_t abbrev_offset = read_from_pointer<64>(&debug_info);
290          uint8_t address_size = read_from_pointer<8>(&debug_info);
291          size_t LEB_size;
292          uint64_t abbreviation_number = read_unsigned_LEB_128(debug_info,
293                                                               &LEB_size);
294          debug_info += LEB_size;
295          unsigned char* die_abbrev = this->associated_abbrev_->get_new_abbrev(
296              &abbreviation_number, abbrev_offset);
297          unsigned char* die_end;
298          if (!this->get_die_end(debug_info, die_abbrev, &die_end,
299                                 debug_info_end, address_size, true))
300            {
301              this->failed(_("Invalid DIE in debug info; "
302			     "failed to reduce debug info"));
303              return;
304            }
305
306          insert_into_vector<32>(&this->data_, 0xFFFFFFFF);
307          insert_into_vector<32>(&this->data_, 0);
308          insert_into_vector<64>(
309              &this->data_,
310              (11 + get_length_as_unsigned_LEB_128(abbreviation_number)
311	       + die_end - debug_info));
312          insert_into_vector<16>(&this->data_, version);
313          insert_into_vector<64>(&this->data_, 0);
314          insert_into_vector<8>(&this->data_, address_size);
315          write_unsigned_LEB_128(&this->data_, abbreviation_number);
316          this->data_.insert(this->data_.end(), debug_info, die_end);
317        }
318      else
319        {
320          const int dwarf32_header_size =
321              sizeof(uint16_t) + sizeof(uint32_t) + sizeof(uint8_t);
322          if (debug_info + dwarf32_header_size >= debug_info_end)
323            {
324              this->failed(_("Debug info extends beyond .debug_info section; "
325			     "failed to reduce debug info"));
326              return;
327            }
328          uint32_t compile_unit_size = compile_unit_start;
329          next_compile_unit = debug_info + compile_unit_size;
330          uint16_t version = read_from_pointer<16>(&debug_info);
331          uint32_t abbrev_offset = read_from_pointer<32>(&debug_info);
332          uint8_t address_size = read_from_pointer<8>(&debug_info);
333          size_t LEB_size;
334          uint64_t abbreviation_number = read_unsigned_LEB_128(debug_info,
335                                                               &LEB_size);
336          debug_info += LEB_size;
337          unsigned char* die_abbrev = this->associated_abbrev_->get_new_abbrev(
338              &abbreviation_number, abbrev_offset);
339          unsigned char* die_end;
340          if (!this->get_die_end(debug_info, die_abbrev, &die_end,
341                                 debug_info_end, address_size, false))
342            {
343              this->failed(_("Invalid DIE in debug info; "
344			     "failed to reduce debug info"));
345              return;
346            }
347
348          insert_into_vector<32>(
349              &this->data_,
350              (7 + get_length_as_unsigned_LEB_128(abbreviation_number)
351	       + die_end - debug_info));
352          insert_into_vector<16>(&this->data_, version);
353          insert_into_vector<32>(&this->data_, 0);
354          insert_into_vector<8>(&this->data_, address_size);
355          write_unsigned_LEB_128(&this->data_, abbreviation_number);
356          this->data_.insert(this->data_.end(), debug_info, die_end);
357        }
358      debug_info = next_compile_unit;
359    }
360  this->set_data_size(data_.size());
361}
362
363void Output_reduced_debug_info_section::do_write(Output_file* of)
364{
365  off_t offset = this->offset();
366  off_t data_size = this->data_size();
367  unsigned char* view = of->get_output_view(offset, data_size);
368  if (this->failed_)
369    memcpy(view, this->postprocessing_buffer(),
370           this->postprocessing_buffer_size());
371  else
372    memcpy(view, &this->data_.front(), data_size);
373  of->write_output_view(offset, data_size, view);
374}
375
376} // End namespace gold.
377