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