Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2010 Google Inc. All Rights Reserved. | 1 // Copyright (c) 2010 Google Inc. All Rights Reserved. |
| 2 // | 2 // |
| 3 // Redistribution and use in source and binary forms, with or without | 3 // Redistribution and use in source and binary forms, with or without |
| 4 // modification, are permitted provided that the following conditions are | 4 // modification, are permitted provided that the following conditions are |
| 5 // met: | 5 // met: |
| 6 // | 6 // |
| 7 // * Redistributions of source code must retain the above copyright | 7 // * Redistributions of source code must retain the above copyright |
| 8 // notice, this list of conditions and the following disclaimer. | 8 // notice, this list of conditions and the following disclaimer. |
| 9 // * Redistributions in binary form must reproduce the above | 9 // * Redistributions in binary form must reproduce the above |
| 10 // copyright notice, this list of conditions and the following disclaimer | 10 // copyright notice, this list of conditions and the following disclaimer |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 37 #include <stdint.h> | 37 #include <stdint.h> |
| 38 #include <stdio.h> | 38 #include <stdio.h> |
| 39 #include <string.h> | 39 #include <string.h> |
| 40 | 40 |
| 41 #include <map> | 41 #include <map> |
| 42 #include <memory> | 42 #include <memory> |
| 43 #include <stack> | 43 #include <stack> |
| 44 #include <string> | 44 #include <string> |
| 45 #include <utility> | 45 #include <utility> |
| 46 | 46 |
| 47 #include <sys/stat.h> | |
| 48 | |
| 47 #include "common/dwarf/bytereader-inl.h" | 49 #include "common/dwarf/bytereader-inl.h" |
| 48 #include "common/dwarf/bytereader.h" | 50 #include "common/dwarf/bytereader.h" |
| 49 #include "common/dwarf/line_state_machine.h" | 51 #include "common/dwarf/line_state_machine.h" |
| 50 #include "common/using_std_string.h" | 52 #include "common/using_std_string.h" |
| 51 | 53 |
| 52 namespace dwarf2reader { | 54 namespace dwarf2reader { |
| 53 | 55 |
| 54 CompilationUnit::CompilationUnit(const SectionMap& sections, uint64 offset, | 56 CompilationUnit::CompilationUnit(const string& path, |
| 57 const SectionMap& sections, uint64 offset, | |
| 55 ByteReader* reader, Dwarf2Handler* handler) | 58 ByteReader* reader, Dwarf2Handler* handler) |
| 56 : offset_from_section_start_(offset), reader_(reader), | 59 : path_(path), offset_from_section_start_(offset), reader_(reader), |
| 57 sections_(sections), handler_(handler), abbrevs_(NULL), | 60 sections_(sections), handler_(handler), abbrevs_(), |
| 58 string_buffer_(NULL), string_buffer_length_(0) {} | 61 string_buffer_(NULL), string_buffer_length_(0), |
| 62 str_offsets_buffer_(NULL), str_offsets_buffer_length_(0), | |
| 63 addr_buffer_(NULL), addr_buffer_length_(0), | |
| 64 is_split_dwarf_(false), dwo_id_(0), dwo_name_(), | |
| 65 skeleton_dwo_id_(0), ranges_base_(0), addr_base_(0), | |
| 66 have_checked_for_dwp_(false), dwp_path_(), | |
| 67 dwp_byte_reader_(), dwp_reader_() {} | |
| 68 | |
| 69 // Initialize a compilation unit from a .dwo or .dwp file. | |
| 70 // In this case, we need the .debug_addr section from the | |
| 71 // executable file that contains the corresponding skeleton | |
| 72 // compilation unit. We also inherit the Dwarf2Handler from | |
| 73 // the executable file, and call it as if we were still | |
| 74 // processing the original compilation unit. | |
| 75 | |
| 76 void CompilationUnit::SetSplitDwarf(const uint8_t* addr_buffer, | |
| 77 uint64 addr_buffer_length, | |
| 78 uint64 addr_base, | |
| 79 uint64 ranges_base, | |
| 80 uint64 dwo_id) { | |
| 81 is_split_dwarf_ = true; | |
| 82 addr_buffer_ = addr_buffer; | |
| 83 addr_buffer_length_ = addr_buffer_length; | |
| 84 addr_base_ = addr_base; | |
| 85 ranges_base_ = ranges_base; | |
| 86 skeleton_dwo_id_ = dwo_id; | |
| 87 } | |
| 59 | 88 |
| 60 // Read a DWARF2/3 abbreviation section. | 89 // Read a DWARF2/3 abbreviation section. |
| 61 // Each abbrev consists of a abbreviation number, a tag, a byte | 90 // Each abbrev consists of a abbreviation number, a tag, a byte |
| 62 // specifying whether the tag has children, and a list of | 91 // specifying whether the tag has children, and a list of |
| 63 // attribute/form pairs. | 92 // attribute/form pairs. |
| 64 // The list of forms is terminated by a 0 for the attribute, and a | 93 // The list of forms is terminated by a 0 for the attribute, and a |
| 65 // zero for the form. The entire abbreviation section is terminated | 94 // zero for the form. The entire abbreviation section is terminated |
| 66 // by a zero for the code. | 95 // by a zero for the code. |
| 67 | 96 |
| 68 void CompilationUnit::ReadAbbrevs() { | 97 void CompilationUnit::ReadAbbrevs() { |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 167 case DW_FORM_data4: | 196 case DW_FORM_data4: |
| 168 return start + 4; | 197 return start + 4; |
| 169 case DW_FORM_ref8: | 198 case DW_FORM_ref8: |
| 170 case DW_FORM_data8: | 199 case DW_FORM_data8: |
| 171 case DW_FORM_ref_sig8: | 200 case DW_FORM_ref_sig8: |
| 172 return start + 8; | 201 return start + 8; |
| 173 case DW_FORM_string: | 202 case DW_FORM_string: |
| 174 return start + strlen(reinterpret_cast<const char *>(start)) + 1; | 203 return start + strlen(reinterpret_cast<const char *>(start)) + 1; |
| 175 case DW_FORM_udata: | 204 case DW_FORM_udata: |
| 176 case DW_FORM_ref_udata: | 205 case DW_FORM_ref_udata: |
| 206 case DW_FORM_GNU_str_index: | |
| 207 case DW_FORM_GNU_addr_index: | |
| 177 reader_->ReadUnsignedLEB128(start, &len); | 208 reader_->ReadUnsignedLEB128(start, &len); |
| 178 return start + len; | 209 return start + len; |
| 179 | 210 |
| 180 case DW_FORM_sdata: | 211 case DW_FORM_sdata: |
| 181 reader_->ReadSignedLEB128(start, &len); | 212 reader_->ReadSignedLEB128(start, &len); |
| 182 return start + len; | 213 return start + len; |
| 183 case DW_FORM_addr: | 214 case DW_FORM_addr: |
| 184 return start + reader_->AddressSize(); | 215 return start + reader_->AddressSize(); |
| 185 case DW_FORM_ref_addr: | 216 case DW_FORM_ref_addr: |
| 186 // DWARF2 and 3/4 differ on whether ref_addr is address size or | 217 // DWARF2 and 3/4 differ on whether ref_addr is address size or |
| (...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 // recommended in the DWARF spec, and used on Linux; "__debug_str" | 320 // recommended in the DWARF spec, and used on Linux; "__debug_str" |
| 290 // is the name used in Mac OS X Mach-O files. | 321 // is the name used in Mac OS X Mach-O files. |
| 291 iter = sections_.find(".debug_str"); | 322 iter = sections_.find(".debug_str"); |
| 292 if (iter == sections_.end()) | 323 if (iter == sections_.end()) |
| 293 iter = sections_.find("__debug_str"); | 324 iter = sections_.find("__debug_str"); |
| 294 if (iter != sections_.end()) { | 325 if (iter != sections_.end()) { |
| 295 string_buffer_ = iter->second.first; | 326 string_buffer_ = iter->second.first; |
| 296 string_buffer_length_ = iter->second.second; | 327 string_buffer_length_ = iter->second.second; |
| 297 } | 328 } |
| 298 | 329 |
| 330 // Set the string offsets section if we have one. | |
| 331 iter = sections_.find(".debug_str_offsets"); | |
| 332 if (iter != sections_.end()) { | |
| 333 str_offsets_buffer_ = iter->second.first; | |
| 334 str_offsets_buffer_length_ = iter->second.second; | |
| 335 } | |
| 336 | |
| 337 // Set the address section if we have one. | |
| 338 iter = sections_.find(".debug_addr"); | |
| 339 if (iter != sections_.end()) { | |
| 340 addr_buffer_ = iter->second.first; | |
| 341 addr_buffer_length_ = iter->second.second; | |
| 342 } | |
| 343 | |
| 299 // Now that we have our abbreviations, start processing DIE's. | 344 // Now that we have our abbreviations, start processing DIE's. |
| 300 ProcessDIEs(); | 345 ProcessDIEs(); |
| 301 | 346 |
| 347 // If this is a skeleton compilation unit generated with split DWARF, | |
| 348 // and the client needs the full debug info, we need to find the full | |
| 349 // compilation unit in a .dwo or .dwp file. | |
| 350 if (!is_split_dwarf_ | |
| 351 && dwo_name_ != NULL | |
| 352 && handler_->NeedSplitDebugInfo()) | |
| 353 ProcessSplitDwarf(); | |
| 354 | |
| 302 return ourlength; | 355 return ourlength; |
| 303 } | 356 } |
| 304 | 357 |
| 305 // If one really wanted, you could merge SkipAttribute and | 358 // If one really wanted, you could merge SkipAttribute and |
| 306 // ProcessAttribute | 359 // ProcessAttribute |
| 307 // This is all boring data manipulation and calling of the handler. | 360 // This is all boring data manipulation and calling of the handler. |
| 308 const uint8_t *CompilationUnit::ProcessAttribute( | 361 const uint8_t *CompilationUnit::ProcessAttribute( |
| 309 uint64 dieoffset, const uint8_t *start, enum DwarfAttribute attr, | 362 uint64 dieoffset, const uint8_t *start, enum DwarfAttribute attr, |
| 310 enum DwarfForm form) { | 363 enum DwarfForm form) { |
| 311 size_t len; | 364 size_t len; |
| 312 | 365 |
| 313 switch (form) { | 366 switch (form) { |
| 314 // DW_FORM_indirect is never used because it is such a space | 367 // DW_FORM_indirect is never used because it is such a space |
| 315 // waster. | 368 // waster. |
| 316 case DW_FORM_indirect: | 369 case DW_FORM_indirect: |
| 317 form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start, | 370 form = static_cast<enum DwarfForm>(reader_->ReadUnsignedLEB128(start, |
| 318 &len)); | 371 &len)); |
| 319 start += len; | 372 start += len; |
| 320 return ProcessAttribute(dieoffset, start, attr, form); | 373 return ProcessAttribute(dieoffset, start, attr, form); |
| 321 | 374 |
| 322 case DW_FORM_flag_present: | 375 case DW_FORM_flag_present: |
| 323 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, 1); | 376 ProcessAttributeUnsigned(dieoffset, attr, form, 1); |
| 324 return start; | 377 return start; |
| 325 case DW_FORM_data1: | 378 case DW_FORM_data1: |
| 326 case DW_FORM_flag: | 379 case DW_FORM_flag: |
| 327 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 380 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 328 reader_->ReadOneByte(start)); | 381 reader_->ReadOneByte(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 329 return start + 1; | 382 return start + 1; |
| 330 case DW_FORM_data2: | 383 case DW_FORM_data2: |
| 331 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 384 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 332 reader_->ReadTwoBytes(start)); | 385 reader_->ReadTwoBytes(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 333 return start + 2; | 386 return start + 2; |
| 334 case DW_FORM_data4: | 387 case DW_FORM_data4: |
| 335 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 388 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 336 reader_->ReadFourBytes(start)); | 389 reader_->ReadFourBytes(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 337 return start + 4; | 390 return start + 4; |
| 338 case DW_FORM_data8: | 391 case DW_FORM_data8: |
| 339 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 392 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 340 reader_->ReadEightBytes(start)); | 393 reader_->ReadEightBytes(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:51
Done.
| |
| 341 return start + 8; | 394 return start + 8; |
| 342 case DW_FORM_string: { | 395 case DW_FORM_string: { |
| 343 const char *str = reinterpret_cast<const char *>(start); | 396 const char *str = reinterpret_cast<const char *>(start); |
| 344 handler_->ProcessAttributeString(dieoffset, attr, form, | 397 ProcessAttributeString(dieoffset, attr, form, |
| 345 str); | 398 str); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change -- j
yunlian
2016/04/18 21:20:51
Done.
| |
| 346 return start + strlen(str) + 1; | 399 return start + strlen(str) + 1; |
| 347 } | 400 } |
| 348 case DW_FORM_udata: | 401 case DW_FORM_udata: |
| 349 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 402 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 350 reader_->ReadUnsignedLEB128(start, | 403 reader_->ReadUnsignedLEB128(start, |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 351 &len)); | 404 &len)); |
| 352 return start + len; | 405 return start + len; |
| 353 | 406 |
| 354 case DW_FORM_sdata: | 407 case DW_FORM_sdata: |
| 355 handler_->ProcessAttributeSigned(dieoffset, attr, form, | 408 ProcessAttributeSigned(dieoffset, attr, form, |
| 356 reader_->ReadSignedLEB128(start, &len)); | 409 reader_->ReadSignedLEB128(start, &len)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 357 return start + len; | 410 return start + len; |
| 358 case DW_FORM_addr: | 411 case DW_FORM_addr: |
| 359 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 412 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 360 reader_->ReadAddress(start)); | 413 reader_->ReadAddress(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:52
Done.
| |
| 361 return start + reader_->AddressSize(); | 414 return start + reader_->AddressSize(); |
| 362 case DW_FORM_sec_offset: | 415 case DW_FORM_sec_offset: |
| 363 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 416 ProcessAttributeUnsigned(dieoffset, attr, form, |
| 364 reader_->ReadOffset(start)); | 417 reader_->ReadOffset(start)); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change
yunlian
2016/04/18 21:20:51
Done.
| |
| 365 return start + reader_->OffsetSize(); | 418 return start + reader_->OffsetSize(); |
| 366 | 419 |
| 367 case DW_FORM_ref1: | 420 case DW_FORM_ref1: |
| 368 handler_->ProcessAttributeReference(dieoffset, attr, form, | 421 handler_->ProcessAttributeReference(dieoffset, attr, form, |
| 369 reader_->ReadOneByte(start) | 422 reader_->ReadOneByte(start) |
| 370 + offset_from_section_start_); | 423 + offset_from_section_start_); |
| 371 return start + 1; | 424 return start + 1; |
| 372 case DW_FORM_ref2: | 425 case DW_FORM_ref2: |
| 373 handler_->ProcessAttributeReference(dieoffset, attr, form, | 426 handler_->ProcessAttributeReference(dieoffset, attr, form, |
| 374 reader_->ReadTwoBytes(start) | 427 reader_->ReadTwoBytes(start) |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 434 datalen); | 487 datalen); |
| 435 return start + datalen + len; | 488 return start + datalen + len; |
| 436 } | 489 } |
| 437 case DW_FORM_strp: { | 490 case DW_FORM_strp: { |
| 438 assert(string_buffer_ != NULL); | 491 assert(string_buffer_ != NULL); |
| 439 | 492 |
| 440 const uint64 offset = reader_->ReadOffset(start); | 493 const uint64 offset = reader_->ReadOffset(start); |
| 441 assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); | 494 assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); |
| 442 | 495 |
| 443 const char *str = reinterpret_cast<const char *>(string_buffer_ + offset); | 496 const char *str = reinterpret_cast<const char *>(string_buffer_ + offset); |
| 444 handler_->ProcessAttributeString(dieoffset, attr, form, | 497 ProcessAttributeString(dieoffset, attr, form, |
| 445 str); | 498 str); |
|
vapier
2016/04/14 22:48:47
line wrapping is broken now after this change -- j
yunlian
2016/04/18 21:20:52
Done.
| |
| 446 return start + reader_->OffsetSize(); | 499 return start + reader_->OffsetSize(); |
| 447 } | 500 } |
| 501 | |
| 502 case DW_FORM_GNU_str_index: { | |
| 503 uint64 str_index = reader_->ReadUnsignedLEB128(start, &len); | |
| 504 const uint8_t* offset_ptr = | |
| 505 str_offsets_buffer_ + str_index * reader_->OffsetSize(); | |
| 506 const uint64 offset = reader_->ReadOffset(offset_ptr); | |
| 507 if (offset >= string_buffer_length_) { | |
| 508 return NULL; | |
| 509 } | |
| 510 | |
| 511 const char* str = reinterpret_cast<const char *>(string_buffer_) + offset; | |
| 512 ProcessAttributeString(dieoffset, attr, form, | |
| 513 str); | |
|
vapier
2016/04/14 22:48:47
line wrapping here looks broken -- just unwrap it
| |
| 514 return start + len; | |
| 515 break; | |
|
vapier
2016/04/14 22:48:47
pointless break -> delete
yunlian
2016/04/14 23:18:49
Done.
| |
| 516 } | |
| 517 case DW_FORM_GNU_addr_index: { | |
| 518 uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len); | |
| 519 const uint8_t* addr_ptr = | |
| 520 addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize(); | |
| 521 ProcessAttributeUnsigned(dieoffset, attr, form, | |
| 522 reader_->ReadAddress(addr_ptr)); | |
|
vapier
2016/04/14 22:48:47
line wrapping is broken
yunlian
2016/04/18 21:20:52
Done.
| |
| 523 return start + len; | |
| 524 break; | |
|
vapier
2016/04/14 22:48:47
pointless break -> delete
yunlian
2016/04/18 21:20:52
Done.
| |
| 525 } | |
| 526 | |
| 527 | |
|
vapier
2016/04/14 22:48:47
only one blank line here
yunlian
2016/04/18 21:20:52
Done.
| |
| 448 } | 528 } |
| 449 fprintf(stderr, "Unhandled form type\n"); | 529 fprintf(stderr, "Unhandled form type\n"); |
| 450 return NULL; | 530 return NULL; |
| 451 } | 531 } |
| 452 | 532 |
| 453 const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset, | 533 const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset, |
| 454 const uint8_t *start, | 534 const uint8_t *start, |
| 455 const Abbrev& abbrev) { | 535 const Abbrev& abbrev) { |
| 456 for (AttributeList::const_iterator i = abbrev.attributes.begin(); | 536 for (AttributeList::const_iterator i = abbrev.attributes.begin(); |
| 457 i != abbrev.attributes.end(); | 537 i != abbrev.attributes.end(); |
| 458 i++) { | 538 i++) { |
| 459 start = ProcessAttribute(dieoffset, start, i->first, i->second); | 539 start = ProcessAttribute(dieoffset, start, i->first, i->second); |
| 460 } | 540 } |
| 541 | |
| 542 // If this is a compilation unit in a split DWARF object, verify that | |
| 543 // the dwo_id matches. If it does not match, we will ignore this | |
| 544 // compilation unit. | |
| 545 if (abbrev.tag == DW_TAG_compile_unit | |
| 546 && is_split_dwarf_ | |
| 547 && dwo_id_ != skeleton_dwo_id_) { | |
| 548 return NULL; | |
| 549 } | |
| 550 | |
| 461 return start; | 551 return start; |
| 462 } | 552 } |
| 463 | 553 |
| 464 void CompilationUnit::ProcessDIEs() { | 554 void CompilationUnit::ProcessDIEs() { |
| 465 const uint8_t *dieptr = after_header_; | 555 const uint8_t *dieptr = after_header_; |
| 466 size_t len; | 556 size_t len; |
| 467 | 557 |
| 468 // lengthstart is the place the length field is based on. | 558 // lengthstart is the place the length field is based on. |
| 469 // It is the point in the header after the initial length field | 559 // It is the point in the header after the initial length field |
| 470 const uint8_t *lengthstart = buffer_; | 560 const uint8_t *lengthstart = buffer_; |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 508 } | 598 } |
| 509 | 599 |
| 510 if (abbrev.has_children) { | 600 if (abbrev.has_children) { |
| 511 die_stack.push(absolute_offset); | 601 die_stack.push(absolute_offset); |
| 512 } else { | 602 } else { |
| 513 handler_->EndDIE(absolute_offset); | 603 handler_->EndDIE(absolute_offset); |
| 514 } | 604 } |
| 515 } | 605 } |
| 516 } | 606 } |
| 517 | 607 |
| 608 // Check for a valid ELF file and return the Address size. | |
| 609 // Returns 0 if not a valid ELF file. | |
| 610 | |
| 611 inline int GetElfWidth(const ElfReader& elf) { | |
|
vapier
2016/04/14 22:48:47
i'm not seeing where ElfReader is defined. can yo
yunlian
2016/04/18 21:20:52
The elf_reader.h and elf_reader.cc were missing in
| |
| 612 if (elf.IsElf32File()) | |
| 613 return 4; | |
| 614 if (elf.IsElf64File()) | |
| 615 return 8; | |
| 616 return 0; | |
| 617 } | |
| 618 | |
| 619 void CompilationUnit::ProcessSplitDwarf() { | |
| 620 struct stat statbuf; | |
| 621 if (!have_checked_for_dwp_) { | |
| 622 // Look for a .dwp file in the same directory as the executable. | |
| 623 have_checked_for_dwp_ = true; | |
| 624 string dwp_suffix(".dwp"); | |
| 625 dwp_path_ = path_ + dwp_suffix; | |
| 626 if (stat(dwp_path_.c_str(), &statbuf)) { | |
|
vapier
2016/04/14 22:48:47
compare it against != 0, and put a comment in the
yunlian
2016/04/14 23:18:49
Done.
| |
| 627 string debug_suffix(".debug"); | |
| 628 dwp_path_ = path_; | |
| 629 size_t found = path_.rfind(debug_suffix); | |
| 630 if (found + debug_suffix.length() == path_.length()) | |
| 631 dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix); | |
| 632 } | |
| 633 if (stat(dwp_path_.c_str(), &statbuf) == 0) { | |
| 634 ElfReader* elf = new ElfReader(dwp_path_); | |
| 635 int width = GetElfWidth(*elf); | |
| 636 if (width != 0) { | |
| 637 dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness())); | |
| 638 dwp_byte_reader_->SetAddressSize(width); | |
| 639 dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf)); | |
| 640 dwp_reader_->Initialize(); | |
| 641 } else { | |
| 642 delete elf; | |
| 643 } | |
| 644 } | |
| 645 } | |
| 646 bool found_in_dwp = false; | |
| 647 if (dwp_reader_ != NULL) { | |
| 648 // If we have a .dwp file, read the debug sections for the requested CU. | |
| 649 SectionMap sections; | |
| 650 dwp_reader_->ReadDebugSectionsForCU(dwo_id_, §ions); | |
| 651 if (!sections.empty()) { | |
| 652 found_in_dwp = true; | |
| 653 CompilationUnit dwp_comp_unit(dwp_path_, sections, 0, | |
| 654 dwp_byte_reader_.get(), handler_); | |
| 655 dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_, | |
| 656 ranges_base_, dwo_id_); | |
| 657 dwp_comp_unit.Start(); | |
| 658 } | |
| 659 } | |
| 660 if (!found_in_dwp) { | |
| 661 // If no .dwp file, try to open the .dwo file. | |
| 662 if (stat(dwo_name_, &statbuf) == 0) { | |
| 663 ElfReader elf(dwo_name_); | |
| 664 int width = GetElfWidth(elf); | |
| 665 if (width != 0) { | |
| 666 ByteReader reader(ENDIANNESS_LITTLE); | |
|
vapier
2016/04/14 22:48:47
is hardcoding little endian here correct ? should
yunlian
2016/04/14 23:18:49
Done.
| |
| 667 reader.SetAddressSize(width); | |
| 668 SectionMap sections; | |
| 669 ReadDebugSectionsFromDwo(&elf, §ions); | |
| 670 CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader, | |
| 671 handler_); | |
| 672 dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, | |
| 673 addr_base_, ranges_base_, dwo_id_); | |
| 674 dwo_comp_unit.Start(); | |
| 675 } | |
| 676 } | |
| 677 } | |
| 678 } | |
| 679 | |
| 680 void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, | |
| 681 SectionMap* sections) { | |
| 682 static const char* section_names[] = { | |
|
vapier
2016/04/14 22:48:47
mark the array itself const too
static const cha
yunlian
2016/04/14 23:18:49
Done.
| |
| 683 ".debug_abbrev", | |
| 684 ".debug_info", | |
| 685 ".debug_str_offsets", | |
| 686 ".debug_str" | |
| 687 }; | |
| 688 for (unsigned int i = 0u; i < sizeof(section_names)/sizeof(*(section_names)); ++i) { | |
| 689 string base_name = section_names[i]; | |
| 690 string dwo_name = base_name + ".dwo"; | |
| 691 size_t section_size; | |
| 692 const char* section_data = elf_reader->GetSectionByName(dwo_name, | |
| 693 §ion_size); | |
| 694 if (section_data != NULL) | |
| 695 sections->insert(std::make_pair( | |
| 696 base_name, std::make_pair(reinterpret_cast<const uint8_t *>(section_da ta), section_size))); | |
| 697 } | |
| 698 } | |
| 699 | |
| 700 DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader) | |
| 701 : elf_reader_(elf_reader), byte_reader_(byte_reader), | |
| 702 cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL), | |
| 703 string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0), | |
| 704 nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL), | |
| 705 offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL), | |
| 706 abbrev_size_(0), info_data_(NULL), info_size_(0), | |
| 707 str_offsets_data_(NULL), str_offsets_size_(0) {} | |
| 708 | |
| 709 DwpReader::~DwpReader() { | |
| 710 if (elf_reader_) delete elf_reader_; | |
| 711 } | |
| 712 | |
| 713 void DwpReader::Initialize() { | |
| 714 cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index", | |
| 715 &cu_index_size_); | |
| 716 if (cu_index_ == NULL) { | |
| 717 return; | |
| 718 } | |
| 719 // The .debug_str.dwo section is shared by all CUs in the file. | |
| 720 string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo", | |
| 721 &string_buffer_size_); | |
| 722 | |
| 723 version_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_ind ex_)); | |
| 724 | |
| 725 if (version_ == 1) { | |
| 726 nslots_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
| 727 + 3 * sizeof(uint32)); | |
| 728 phash_ = cu_index_ + 4 * sizeof(uint32); | |
| 729 pindex_ = phash_ + nslots_ * sizeof(uint64); | |
| 730 shndx_pool_ = pindex_ + nslots_ * sizeof(uint32); | |
| 731 if (shndx_pool_ >= cu_index_ + cu_index_size_) { | |
| 732 version_ = 0; | |
| 733 } | |
| 734 } else if (version_ == 2) { | |
| 735 ncolumns_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_ index_) | |
| 736 + sizeof(uint32)); | |
| 737 nunits_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
| 738 + 2 * sizeof(uint32)); | |
| 739 nslots_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
| 740 + 3 * sizeof(uint32)); | |
| 741 phash_ = cu_index_ + 4 * sizeof(uint32); | |
| 742 pindex_ = phash_ + nslots_ * sizeof(uint64); | |
| 743 offset_table_ = pindex_ + nslots_ * sizeof(uint32); | |
| 744 size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32); | |
| 745 abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo", | |
| 746 &abbrev_size_); | |
| 747 info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_); | |
| 748 str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo", | |
| 749 &str_offsets_size_); | |
| 750 if (size_table_ >= cu_index_ + cu_index_size_) { | |
| 751 version_ = 0; | |
| 752 } | |
| 753 } | |
| 754 } | |
| 755 | |
| 756 void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id, | |
| 757 SectionMap* sections) { | |
| 758 if (version_ == 1) { | |
| 759 int slot = LookupCU(dwo_id); | |
| 760 if (slot == -1) { | |
| 761 return; | |
| 762 } | |
| 763 | |
| 764 // The index table points to the section index pool, where we | |
| 765 // can read a list of section indexes for the debug sections | |
| 766 // for the CU whose dwo_id we are looking for. | |
| 767 int index = byte_reader_.ReadFourBytes( | |
| 768 reinterpret_cast<const uint8_t *>(pindex_) | |
| 769 + slot * sizeof(uint32)); | |
| 770 const char* shndx_list = shndx_pool_ + index * sizeof(uint32); | |
| 771 for (;;) { | |
| 772 if (shndx_list >= cu_index_ + cu_index_size_) { | |
| 773 version_ = 0; | |
| 774 return; | |
| 775 } | |
| 776 unsigned int shndx = byte_reader_.ReadFourBytes(reinterpret_cast<const uin t8_t *>(shndx_list)); | |
| 777 shndx_list += sizeof(uint32); | |
| 778 if (shndx == 0) | |
| 779 break; | |
| 780 const char * section_name = elf_reader_->GetSectionName(shndx); | |
|
vapier
2016/04/14 22:48:47
delete the space before the *
yunlian
2016/04/14 23:18:49
Done.
| |
| 781 size_t section_size; | |
| 782 const char* section_data; | |
| 783 // We're only interested in these four debug sections. | |
| 784 // The section names in the .dwo file end with ".dwo", but we | |
| 785 // add them to the sections table with their normal names. | |
| 786 if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) { | |
| 787 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
| 788 sections->insert(std::make_pair( | |
| 789 ".debug_abbrev", std::make_pair(reinterpret_cast<const uint8_t *> (s ection_data), section_size))); | |
| 790 } else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) { | |
| 791 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
| 792 sections->insert(std::make_pair( | |
| 793 ".debug_info", std::make_pair(reinterpret_cast<const uint8_t *> (sec tion_data), section_size))); | |
| 794 } else if (!strncmp(section_name, ".debug_str_offsets", strlen(".debug_str _offsets"))) { | |
| 795 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
| 796 sections->insert(std::make_pair( | |
| 797 ".debug_str_offsets", std::make_pair(reinterpret_cast<const uint8_t *> (section_data), section_size))); | |
| 798 } | |
| 799 } | |
| 800 sections->insert(std::make_pair( | |
| 801 ".debug_str", std::make_pair(reinterpret_cast<const uint8_t *> (string_b uffer_), string_buffer_size_))); | |
| 802 } else if (version_ == 2) { | |
| 803 uint32 index = LookupCUv2(dwo_id); | |
| 804 if (index == 0) { | |
| 805 return; | |
| 806 } | |
| 807 | |
| 808 // The index points to a row in each of the section offsets table | |
| 809 // and the section size table, where we can read the offsets and sizes | |
| 810 // of the contributions to each debug section from the CU whose dwo_id | |
| 811 // we are looking for. Row 0 of the section offsets table has the | |
| 812 // section ids for each column of the table. The size table begins | |
| 813 // with row 1. | |
| 814 const char* id_row = offset_table_; | |
| 815 const char* offset_row = offset_table_ + index * ncolumns_ * sizeof(uint32); | |
| 816 const char* size_row = | |
| 817 size_table_ + (index - 1) * ncolumns_ * sizeof(uint32); | |
| 818 if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) { | |
| 819 version_ = 0; | |
| 820 return; | |
| 821 } | |
| 822 for (unsigned int col = 0u; col < ncolumns_; ++col) { | |
| 823 uint32 section_id = | |
| 824 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row) | |
| 825 + col * sizeof(uint32)); | |
| 826 uint32 offset = | |
| 827 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(offset_ro w) | |
| 828 + col * sizeof(uint32)); | |
| 829 uint32 size = | |
| 830 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(size_row) | |
| 831 + col * sizeof(uint32)); | |
| 832 if (section_id == DW_SECT_ABBREV) { | |
| 833 sections->insert(std::make_pair( | |
| 834 ".debug_abbrev", std::make_pair(reinterpret_cast<const uint8_t *> (a bbrev_data_) + offset, size))); | |
| 835 } else if (section_id == DW_SECT_INFO) { | |
| 836 sections->insert(std::make_pair( | |
| 837 ".debug_info", std::make_pair(reinterpret_cast<const uint8_t *> (inf o_data_) + offset, size))); | |
| 838 } else if (section_id == DW_SECT_STR_OFFSETS) { | |
| 839 sections->insert( | |
| 840 std::make_pair(".debug_str_offsets", | |
| 841 std::make_pair(reinterpret_cast<const uint8_t *> (str _offsets_data_) + offset, size))); | |
| 842 } | |
| 843 } | |
| 844 sections->insert(std::make_pair( | |
| 845 ".debug_str", std::make_pair(reinterpret_cast<const uint8_t *> (string_b uffer_), string_buffer_size_))); | |
| 846 } | |
| 847 } | |
| 848 | |
| 849 int DwpReader::LookupCU(uint64 dwo_id) { | |
| 850 uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1); | |
| 851 uint64 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(p hash_) + slot * sizeof(uint64)); | |
| 852 if (probe != 0 && probe != dwo_id) { | |
| 853 uint32 secondary_hash = | |
| 854 (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1; | |
| 855 do { | |
| 856 slot = (slot + secondary_hash) & (nslots_ - 1); | |
| 857 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(phas h_) + slot * sizeof(uint64)); | |
| 858 } while (probe != 0 && probe != dwo_id); | |
| 859 } | |
| 860 if (probe == 0) | |
| 861 return -1; | |
| 862 return slot; | |
| 863 } | |
| 864 | |
| 865 uint32 DwpReader::LookupCUv2(uint64 dwo_id) { | |
| 866 uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1); | |
| 867 uint64 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(p hash_) + slot * sizeof(uint64)); | |
| 868 uint32 index = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(pi ndex_) + slot * sizeof(uint32)); | |
| 869 if (index != 0 && probe != dwo_id) { | |
| 870 uint32 secondary_hash = | |
| 871 (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1; | |
| 872 do { | |
| 873 slot = (slot + secondary_hash) & (nslots_ - 1); | |
| 874 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(phas h_) + slot * sizeof(uint64)); | |
| 875 index = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(pinde x_) + slot * sizeof(uint32)); | |
| 876 } while (index != 0 && probe != dwo_id); | |
| 877 } | |
| 878 return index; | |
| 879 } | |
| 880 | |
| 881 | |
| 882 | |
| 518 LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length, | 883 LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length, |
| 519 ByteReader* reader, LineInfoHandler* handler): | 884 ByteReader* reader, LineInfoHandler* handler): |
| 520 handler_(handler), reader_(reader), buffer_(buffer) { | 885 handler_(handler), reader_(reader), buffer_(buffer) { |
| 521 #ifndef NDEBUG | 886 #ifndef NDEBUG |
| 522 buffer_length_ = buffer_length; | 887 buffer_length_ = buffer_length; |
| 523 #endif | 888 #endif |
| 524 header_.std_opcode_lengths = NULL; | 889 header_.std_opcode_lengths = NULL; |
| 525 } | 890 } |
| 526 | 891 |
| 527 uint64 LineInfo::Start() { | 892 uint64 LineInfo::Start() { |
| (...skipping 1811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2339 uint64 insn_offset) { | 2704 uint64 insn_offset) { |
| 2340 fprintf(stderr, | 2705 fprintf(stderr, |
| 2341 "%s: CFI %s at offset 0x%llx in section '%s':" | 2706 "%s: CFI %s at offset 0x%llx in section '%s':" |
| 2342 " the DW_CFA_restore_state instruction at offset 0x%llx" | 2707 " the DW_CFA_restore_state instruction at offset 0x%llx" |
| 2343 " would clear the CFA rule in effect\n", | 2708 " would clear the CFA rule in effect\n", |
| 2344 filename_.c_str(), CallFrameInfo::KindName(kind), offset, | 2709 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
| 2345 section_.c_str(), insn_offset); | 2710 section_.c_str(), insn_offset); |
| 2346 } | 2711 } |
| 2347 | 2712 |
| 2348 } // namespace dwarf2reader | 2713 } // namespace dwarf2reader |
| OLD | NEW |