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