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)); |
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)); |
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)); |
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)); |
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, str); |
345 str); | |
346 return start + strlen(str) + 1; | 398 return start + strlen(str) + 1; |
347 } | 399 } |
348 case DW_FORM_udata: | 400 case DW_FORM_udata: |
349 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 401 ProcessAttributeUnsigned(dieoffset, attr, form, |
350 reader_->ReadUnsignedLEB128(start, | 402 reader_->ReadUnsignedLEB128(start, &len)); |
351 &len)); | |
352 return start + len; | 403 return start + len; |
353 | 404 |
354 case DW_FORM_sdata: | 405 case DW_FORM_sdata: |
355 handler_->ProcessAttributeSigned(dieoffset, attr, form, | 406 ProcessAttributeSigned(dieoffset, attr, form, |
356 reader_->ReadSignedLEB128(start, &len)); | 407 reader_->ReadSignedLEB128(start, &len)); |
357 return start + len; | 408 return start + len; |
358 case DW_FORM_addr: | 409 case DW_FORM_addr: |
359 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 410 ProcessAttributeUnsigned(dieoffset, attr, form, |
360 reader_->ReadAddress(start)); | 411 reader_->ReadAddress(start)); |
361 return start + reader_->AddressSize(); | 412 return start + reader_->AddressSize(); |
362 case DW_FORM_sec_offset: | 413 case DW_FORM_sec_offset: |
363 handler_->ProcessAttributeUnsigned(dieoffset, attr, form, | 414 ProcessAttributeUnsigned(dieoffset, attr, form, |
364 reader_->ReadOffset(start)); | 415 reader_->ReadOffset(start)); |
365 return start + reader_->OffsetSize(); | 416 return start + reader_->OffsetSize(); |
366 | 417 |
367 case DW_FORM_ref1: | 418 case DW_FORM_ref1: |
368 handler_->ProcessAttributeReference(dieoffset, attr, form, | 419 handler_->ProcessAttributeReference(dieoffset, attr, form, |
369 reader_->ReadOneByte(start) | 420 reader_->ReadOneByte(start) |
370 + offset_from_section_start_); | 421 + offset_from_section_start_); |
371 return start + 1; | 422 return start + 1; |
372 case DW_FORM_ref2: | 423 case DW_FORM_ref2: |
373 handler_->ProcessAttributeReference(dieoffset, attr, form, | 424 handler_->ProcessAttributeReference(dieoffset, attr, form, |
374 reader_->ReadTwoBytes(start) | 425 reader_->ReadTwoBytes(start) |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
434 datalen); | 485 datalen); |
435 return start + datalen + len; | 486 return start + datalen + len; |
436 } | 487 } |
437 case DW_FORM_strp: { | 488 case DW_FORM_strp: { |
438 assert(string_buffer_ != NULL); | 489 assert(string_buffer_ != NULL); |
439 | 490 |
440 const uint64 offset = reader_->ReadOffset(start); | 491 const uint64 offset = reader_->ReadOffset(start); |
441 assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); | 492 assert(string_buffer_ + offset < string_buffer_ + string_buffer_length_); |
442 | 493 |
443 const char *str = reinterpret_cast<const char *>(string_buffer_ + offset); | 494 const char *str = reinterpret_cast<const char *>(string_buffer_ + offset); |
444 handler_->ProcessAttributeString(dieoffset, attr, form, | 495 ProcessAttributeString(dieoffset, attr, form, str); |
445 str); | |
446 return start + reader_->OffsetSize(); | 496 return start + reader_->OffsetSize(); |
447 } | 497 } |
498 | |
499 case DW_FORM_GNU_str_index: { | |
500 uint64 str_index = reader_->ReadUnsignedLEB128(start, &len); | |
501 const uint8_t* offset_ptr = | |
502 str_offsets_buffer_ + str_index * reader_->OffsetSize(); | |
503 const uint64 offset = reader_->ReadOffset(offset_ptr); | |
504 if (offset >= string_buffer_length_) { | |
505 return NULL; | |
506 } | |
507 | |
508 const char* str = reinterpret_cast<const char *>(string_buffer_) + offset; | |
509 ProcessAttributeString(dieoffset, attr, form, str); | |
510 return start + len; | |
511 break; | |
512 } | |
513 case DW_FORM_GNU_addr_index: { | |
514 uint64 addr_index = reader_->ReadUnsignedLEB128(start, &len); | |
515 const uint8_t* addr_ptr = | |
516 addr_buffer_ + addr_base_ + addr_index * reader_->AddressSize(); | |
517 ProcessAttributeUnsigned(dieoffset, attr, form, | |
518 reader_->ReadAddress(addr_ptr)); | |
519 return start + len; | |
520 } | |
448 } | 521 } |
449 fprintf(stderr, "Unhandled form type\n"); | 522 fprintf(stderr, "Unhandled form type\n"); |
450 return NULL; | 523 return NULL; |
451 } | 524 } |
452 | 525 |
453 const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset, | 526 const uint8_t *CompilationUnit::ProcessDIE(uint64 dieoffset, |
454 const uint8_t *start, | 527 const uint8_t *start, |
455 const Abbrev& abbrev) { | 528 const Abbrev& abbrev) { |
456 for (AttributeList::const_iterator i = abbrev.attributes.begin(); | 529 for (AttributeList::const_iterator i = abbrev.attributes.begin(); |
457 i != abbrev.attributes.end(); | 530 i != abbrev.attributes.end(); |
458 i++) { | 531 i++) { |
459 start = ProcessAttribute(dieoffset, start, i->first, i->second); | 532 start = ProcessAttribute(dieoffset, start, i->first, i->second); |
460 } | 533 } |
534 | |
535 // If this is a compilation unit in a split DWARF object, verify that | |
536 // the dwo_id matches. If it does not match, we will ignore this | |
537 // compilation unit. | |
538 if (abbrev.tag == DW_TAG_compile_unit | |
539 && is_split_dwarf_ | |
540 && dwo_id_ != skeleton_dwo_id_) { | |
541 return NULL; | |
542 } | |
543 | |
461 return start; | 544 return start; |
462 } | 545 } |
463 | 546 |
464 void CompilationUnit::ProcessDIEs() { | 547 void CompilationUnit::ProcessDIEs() { |
465 const uint8_t *dieptr = after_header_; | 548 const uint8_t *dieptr = after_header_; |
466 size_t len; | 549 size_t len; |
467 | 550 |
468 // lengthstart is the place the length field is based on. | 551 // lengthstart is the place the length field is based on. |
469 // It is the point in the header after the initial length field | 552 // It is the point in the header after the initial length field |
470 const uint8_t *lengthstart = buffer_; | 553 const uint8_t *lengthstart = buffer_; |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
508 } | 591 } |
509 | 592 |
510 if (abbrev.has_children) { | 593 if (abbrev.has_children) { |
511 die_stack.push(absolute_offset); | 594 die_stack.push(absolute_offset); |
512 } else { | 595 } else { |
513 handler_->EndDIE(absolute_offset); | 596 handler_->EndDIE(absolute_offset); |
514 } | 597 } |
515 } | 598 } |
516 } | 599 } |
517 | 600 |
601 // Check for a valid ELF file and return the Address size. | |
602 // Returns 0 if not a valid ELF file. | |
603 | |
ivanpe
2016/04/27 01:11:44
Please, do not leave a blank line here.
yunlian
2016/04/27 16:35:29
Done.
| |
604 inline int GetElfWidth(const ElfReader& elf) { | |
605 if (elf.IsElf32File()) | |
606 return 4; | |
607 if (elf.IsElf64File()) | |
608 return 8; | |
609 return 0; | |
610 } | |
611 | |
612 void CompilationUnit::ProcessSplitDwarf() { | |
ivanpe
2016/04/27 01:11:44
It looks like the code that follows comes from: ht
yunlian
2016/04/27 16:35:29
Done.
| |
613 struct stat statbuf; | |
614 if (!have_checked_for_dwp_) { | |
615 // Look for a .dwp file in the same directory as the executable. | |
616 have_checked_for_dwp_ = true; | |
617 string dwp_suffix(".dwp"); | |
618 dwp_path_ = path_ + dwp_suffix; | |
619 if (stat(dwp_path_.c_str(), &statbuf) != 0) { | |
620 // Fall back to a split .debug file in the same directory. | |
621 string debug_suffix(".debug"); | |
622 dwp_path_ = path_; | |
623 size_t found = path_.rfind(debug_suffix); | |
624 if (found + debug_suffix.length() == path_.length()) | |
625 dwp_path_ = dwp_path_.replace(found, debug_suffix.length(), dwp_suffix); | |
626 } | |
627 if (stat(dwp_path_.c_str(), &statbuf) == 0) { | |
628 ElfReader* elf = new ElfReader(dwp_path_); | |
629 int width = GetElfWidth(*elf); | |
630 if (width != 0) { | |
631 dwp_byte_reader_.reset(new ByteReader(reader_->GetEndianness())); | |
632 dwp_byte_reader_->SetAddressSize(width); | |
633 dwp_reader_.reset(new DwpReader(*dwp_byte_reader_, elf)); | |
634 dwp_reader_->Initialize(); | |
635 } else { | |
636 delete elf; | |
637 } | |
638 } | |
639 } | |
640 bool found_in_dwp = false; | |
641 if (dwp_reader_ != NULL) { | |
642 // If we have a .dwp file, read the debug sections for the requested CU. | |
643 SectionMap sections; | |
644 dwp_reader_->ReadDebugSectionsForCU(dwo_id_, §ions); | |
645 if (!sections.empty()) { | |
646 found_in_dwp = true; | |
647 CompilationUnit dwp_comp_unit(dwp_path_, sections, 0, | |
648 dwp_byte_reader_.get(), handler_); | |
649 dwp_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, addr_base_, | |
650 ranges_base_, dwo_id_); | |
651 dwp_comp_unit.Start(); | |
652 } | |
653 } | |
654 if (!found_in_dwp) { | |
655 // If no .dwp file, try to open the .dwo file. | |
656 if (stat(dwo_name_, &statbuf) == 0) { | |
657 ElfReader elf(dwo_name_); | |
658 int width = GetElfWidth(elf); | |
659 if (width != 0) { | |
660 ByteReader reader(ENDIANNESS_LITTLE); | |
661 reader.SetAddressSize(width); | |
662 SectionMap sections; | |
663 ReadDebugSectionsFromDwo(&elf, §ions); | |
664 CompilationUnit dwo_comp_unit(dwo_name_, sections, 0, &reader, | |
665 handler_); | |
666 dwo_comp_unit.SetSplitDwarf(addr_buffer_, addr_buffer_length_, | |
667 addr_base_, ranges_base_, dwo_id_); | |
668 dwo_comp_unit.Start(); | |
669 } | |
670 } | |
671 } | |
672 } | |
673 | |
674 void CompilationUnit::ReadDebugSectionsFromDwo(ElfReader* elf_reader, | |
675 SectionMap* sections) { | |
ivanpe
2016/04/27 01:11:44
indent is off.
yunlian
2016/04/27 16:35:29
Done.
| |
676 static const char* const section_names[] = { | |
677 ".debug_abbrev", | |
678 ".debug_info", | |
679 ".debug_str_offsets", | |
680 ".debug_str" | |
681 }; | |
682 for (unsigned int i = 0u; i < sizeof(section_names)/sizeof(*(section_names)); ++i) { | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
683 string base_name = section_names[i]; | |
684 string dwo_name = base_name + ".dwo"; | |
685 size_t section_size; | |
686 const char* section_data = elf_reader->GetSectionByName(dwo_name, | |
687 §ion_size); | |
688 if (section_data != NULL) | |
689 sections->insert(std::make_pair( | |
690 base_name, std::make_pair(reinterpret_cast<const uint8_t *>(section_da ta), section_size))); | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:29
Done.
| |
691 } | |
692 } | |
693 | |
694 DwpReader::DwpReader(const ByteReader& byte_reader, ElfReader* elf_reader) | |
695 : elf_reader_(elf_reader), byte_reader_(byte_reader), | |
696 cu_index_(NULL), cu_index_size_(0), string_buffer_(NULL), | |
697 string_buffer_size_(0), version_(0), ncolumns_(0), nunits_(0), | |
698 nslots_(0), phash_(NULL), pindex_(NULL), shndx_pool_(NULL), | |
699 offset_table_(NULL), size_table_(NULL), abbrev_data_(NULL), | |
700 abbrev_size_(0), info_data_(NULL), info_size_(0), | |
701 str_offsets_data_(NULL), str_offsets_size_(0) {} | |
702 | |
703 DwpReader::~DwpReader() { | |
704 if (elf_reader_) delete elf_reader_; | |
705 } | |
706 | |
707 void DwpReader::Initialize() { | |
708 cu_index_ = elf_reader_->GetSectionByName(".debug_cu_index", | |
709 &cu_index_size_); | |
710 if (cu_index_ == NULL) { | |
711 return; | |
712 } | |
713 // The .debug_str.dwo section is shared by all CUs in the file. | |
714 string_buffer_ = elf_reader_->GetSectionByName(".debug_str.dwo", | |
715 &string_buffer_size_); | |
716 | |
717 version_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_ind ex_)); | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
718 | |
719 if (version_ == 1) { | |
720 nslots_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
721 + 3 * sizeof(uint32)); | |
722 phash_ = cu_index_ + 4 * sizeof(uint32); | |
723 pindex_ = phash_ + nslots_ * sizeof(uint64); | |
724 shndx_pool_ = pindex_ + nslots_ * sizeof(uint32); | |
725 if (shndx_pool_ >= cu_index_ + cu_index_size_) { | |
726 version_ = 0; | |
727 } | |
728 } else if (version_ == 2) { | |
729 ncolumns_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_ index_) | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
730 + sizeof(uint32)); | |
731 nunits_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
732 + 2 * sizeof(uint32)); | |
733 nslots_ = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(cu_in dex_) | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
yunlian
2016/04/27 16:35:28
Done.
| |
734 + 3 * sizeof(uint32)); | |
735 phash_ = cu_index_ + 4 * sizeof(uint32); | |
736 pindex_ = phash_ + nslots_ * sizeof(uint64); | |
737 offset_table_ = pindex_ + nslots_ * sizeof(uint32); | |
738 size_table_ = offset_table_ + ncolumns_ * (nunits_ + 1) * sizeof(uint32); | |
739 abbrev_data_ = elf_reader_->GetSectionByName(".debug_abbrev.dwo", | |
740 &abbrev_size_); | |
741 info_data_ = elf_reader_->GetSectionByName(".debug_info.dwo", &info_size_); | |
742 str_offsets_data_ = elf_reader_->GetSectionByName(".debug_str_offsets.dwo", | |
743 &str_offsets_size_); | |
744 if (size_table_ >= cu_index_ + cu_index_size_) { | |
745 version_ = 0; | |
746 } | |
747 } | |
748 } | |
749 | |
750 void DwpReader::ReadDebugSectionsForCU(uint64 dwo_id, | |
751 SectionMap* sections) { | |
752 if (version_ == 1) { | |
753 int slot = LookupCU(dwo_id); | |
754 if (slot == -1) { | |
755 return; | |
756 } | |
757 | |
758 // The index table points to the section index pool, where we | |
759 // can read a list of section indexes for the debug sections | |
760 // for the CU whose dwo_id we are looking for. | |
761 int index = byte_reader_.ReadFourBytes( | |
762 reinterpret_cast<const uint8_t *>(pindex_) | |
763 + slot * sizeof(uint32)); | |
764 const char* shndx_list = shndx_pool_ + index * sizeof(uint32); | |
765 for (;;) { | |
766 if (shndx_list >= cu_index_ + cu_index_size_) { | |
767 version_ = 0; | |
768 return; | |
769 } | |
770 unsigned int shndx = byte_reader_.ReadFourBytes(reinterpret_cast<const uin t8_t *>(shndx_list)); | |
ivanpe
2016/04/27 01:11:44
Lines should be <= 80 chars long
Please, apply to
yunlian
2016/04/27 16:35:29
Done.
| |
771 shndx_list += sizeof(uint32); | |
772 if (shndx == 0) | |
773 break; | |
774 const char* section_name = elf_reader_->GetSectionName(shndx); | |
775 size_t section_size; | |
776 const char* section_data; | |
777 // We're only interested in these four debug sections. | |
778 // The section names in the .dwo file end with ".dwo", but we | |
779 // add them to the sections table with their normal names. | |
780 if (!strncmp(section_name, ".debug_abbrev", strlen(".debug_abbrev"))) { | |
781 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
782 sections->insert(std::make_pair( | |
783 ".debug_abbrev", std::make_pair(reinterpret_cast<const uint8_t *> (s ection_data), section_size))); | |
784 } else if (!strncmp(section_name, ".debug_info", strlen(".debug_info"))) { | |
785 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
786 sections->insert(std::make_pair( | |
787 ".debug_info", std::make_pair(reinterpret_cast<const uint8_t *> (sec tion_data), section_size))); | |
788 } else if (!strncmp(section_name, ".debug_str_offsets", strlen(".debug_str _offsets"))) { | |
789 section_data = elf_reader_->GetSectionByIndex(shndx, §ion_size); | |
790 sections->insert(std::make_pair( | |
791 ".debug_str_offsets", std::make_pair(reinterpret_cast<const uint8_t *> (section_data), section_size))); | |
792 } | |
793 } | |
794 sections->insert(std::make_pair( | |
795 ".debug_str", std::make_pair(reinterpret_cast<const uint8_t *> (string_b uffer_), string_buffer_size_))); | |
796 } else if (version_ == 2) { | |
797 uint32 index = LookupCUv2(dwo_id); | |
798 if (index == 0) { | |
799 return; | |
800 } | |
801 | |
802 // The index points to a row in each of the section offsets table | |
803 // and the section size table, where we can read the offsets and sizes | |
804 // of the contributions to each debug section from the CU whose dwo_id | |
805 // we are looking for. Row 0 of the section offsets table has the | |
806 // section ids for each column of the table. The size table begins | |
807 // with row 1. | |
808 const char* id_row = offset_table_; | |
809 const char* offset_row = offset_table_ + index * ncolumns_ * sizeof(uint32); | |
810 const char* size_row = | |
811 size_table_ + (index - 1) * ncolumns_ * sizeof(uint32); | |
812 if (size_row + ncolumns_ * sizeof(uint32) > cu_index_ + cu_index_size_) { | |
813 version_ = 0; | |
814 return; | |
815 } | |
816 for (unsigned int col = 0u; col < ncolumns_; ++col) { | |
817 uint32 section_id = | |
818 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(id_row) | |
819 + col * sizeof(uint32)); | |
820 uint32 offset = | |
821 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(offset_ro w) | |
822 + col * sizeof(uint32)); | |
823 uint32 size = | |
824 byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(size_row) | |
825 + col * sizeof(uint32)); | |
826 if (section_id == DW_SECT_ABBREV) { | |
827 sections->insert(std::make_pair( | |
828 ".debug_abbrev", std::make_pair(reinterpret_cast<const uint8_t *> (a bbrev_data_) + offset, size))); | |
829 } else if (section_id == DW_SECT_INFO) { | |
830 sections->insert(std::make_pair( | |
831 ".debug_info", std::make_pair(reinterpret_cast<const uint8_t *> (inf o_data_) + offset, size))); | |
832 } else if (section_id == DW_SECT_STR_OFFSETS) { | |
833 sections->insert( | |
834 std::make_pair(".debug_str_offsets", | |
835 std::make_pair(reinterpret_cast<const uint8_t *> (str _offsets_data_) + offset, size))); | |
836 } | |
837 } | |
838 sections->insert(std::make_pair( | |
839 ".debug_str", std::make_pair(reinterpret_cast<const uint8_t *> (string_b uffer_), string_buffer_size_))); | |
840 } | |
841 } | |
842 | |
843 int DwpReader::LookupCU(uint64 dwo_id) { | |
844 uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1); | |
845 uint64 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(p hash_) + slot * sizeof(uint64)); | |
846 if (probe != 0 && probe != dwo_id) { | |
847 uint32 secondary_hash = | |
848 (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1; | |
849 do { | |
850 slot = (slot + secondary_hash) & (nslots_ - 1); | |
851 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(phas h_) + slot * sizeof(uint64)); | |
852 } while (probe != 0 && probe != dwo_id); | |
853 } | |
854 if (probe == 0) | |
855 return -1; | |
856 return slot; | |
857 } | |
858 | |
859 uint32 DwpReader::LookupCUv2(uint64 dwo_id) { | |
860 uint32 slot = static_cast<uint32>(dwo_id) & (nslots_ - 1); | |
861 uint64 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(p hash_) + slot * sizeof(uint64)); | |
862 uint32 index = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(pi ndex_) + slot * sizeof(uint32)); | |
863 if (index != 0 && probe != dwo_id) { | |
864 uint32 secondary_hash = | |
865 (static_cast<uint32>(dwo_id >> 32) & (nslots_ - 1)) | 1; | |
866 do { | |
867 slot = (slot + secondary_hash) & (nslots_ - 1); | |
868 probe = byte_reader_.ReadEightBytes(reinterpret_cast<const uint8_t *>(phas h_) + slot * sizeof(uint64)); | |
869 index = byte_reader_.ReadFourBytes(reinterpret_cast<const uint8_t *>(pinde x_) + slot * sizeof(uint32)); | |
870 } while (index != 0 && probe != dwo_id); | |
871 } | |
872 return index; | |
873 } | |
874 | |
518 LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length, | 875 LineInfo::LineInfo(const uint8_t *buffer, uint64 buffer_length, |
519 ByteReader* reader, LineInfoHandler* handler): | 876 ByteReader* reader, LineInfoHandler* handler): |
520 handler_(handler), reader_(reader), buffer_(buffer) { | 877 handler_(handler), reader_(reader), buffer_(buffer) { |
521 #ifndef NDEBUG | 878 #ifndef NDEBUG |
522 buffer_length_ = buffer_length; | 879 buffer_length_ = buffer_length; |
523 #endif | 880 #endif |
524 header_.std_opcode_lengths = NULL; | 881 header_.std_opcode_lengths = NULL; |
525 } | 882 } |
526 | 883 |
527 uint64 LineInfo::Start() { | 884 uint64 LineInfo::Start() { |
(...skipping 1811 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2339 uint64 insn_offset) { | 2696 uint64 insn_offset) { |
2340 fprintf(stderr, | 2697 fprintf(stderr, |
2341 "%s: CFI %s at offset 0x%llx in section '%s':" | 2698 "%s: CFI %s at offset 0x%llx in section '%s':" |
2342 " the DW_CFA_restore_state instruction at offset 0x%llx" | 2699 " the DW_CFA_restore_state instruction at offset 0x%llx" |
2343 " would clear the CFA rule in effect\n", | 2700 " would clear the CFA rule in effect\n", |
2344 filename_.c_str(), CallFrameInfo::KindName(kind), offset, | 2701 filename_.c_str(), CallFrameInfo::KindName(kind), offset, |
2345 section_.c_str(), insn_offset); | 2702 section_.c_str(), insn_offset); |
2346 } | 2703 } |
2347 | 2704 |
2348 } // namespace dwarf2reader | 2705 } // namespace dwarf2reader |
OLD | NEW |