1 // reduced_debug_output.cc -- output reduced debugging information to save space 2 3 // Copyright (C) 2008-2014 Free Software Foundation, Inc. 4 // Written by Caleb Howe <cshowe (at) 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 34 namespace 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. 42 bool 43 Output_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 140 void 141 Output_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 222 void 223 Output_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. 240 unsigned char* 241 Output_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 251 void 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 363 void 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