OLD | NEW |
1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 1 // Copyright 2014 The Crashpad Authors. All rights reserved. |
2 // | 2 // |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
4 // you may not use this file except in compliance with the License. | 4 // you may not use this file except in compliance with the License. |
5 // You may obtain a copy of the License at | 5 // You may obtain a copy of the License at |
6 // | 6 // |
7 // http://www.apache.org/licenses/LICENSE-2.0 | 7 // http://www.apache.org/licenses/LICENSE-2.0 |
8 // | 8 // |
9 // Unless required by applicable law or agreed to in writing, software | 9 // Unless required by applicable law or agreed to in writing, software |
10 // distributed under the License is distributed on an "AS IS" BASIS, | 10 // distributed under the License is distributed on an "AS IS" BASIS, |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
12 // See the License for the specific language governing permissions and | 12 // See the License for the specific language governing permissions and |
13 // limitations under the License. | 13 // limitations under the License. |
14 | 14 |
15 #include "minidump/minidump_thread_writer.h" | 15 #include "minidump/minidump_thread_writer.h" |
16 | 16 |
17 #include <windows.h> | 17 #include <windows.h> |
18 #include <dbghelp.h> | 18 #include <dbghelp.h> |
19 #include <sys/types.h> | 19 #include <sys/types.h> |
20 | 20 |
| 21 #include <string> |
| 22 |
21 #include "base/compiler_specific.h" | 23 #include "base/compiler_specific.h" |
22 #include "base/format_macros.h" | 24 #include "base/format_macros.h" |
23 #include "base/strings/stringprintf.h" | 25 #include "base/strings/stringprintf.h" |
24 #include "gtest/gtest.h" | 26 #include "gtest/gtest.h" |
25 #include "minidump/minidump_context_writer.h" | 27 #include "minidump/minidump_context_writer.h" |
26 #include "minidump/minidump_memory_writer.h" | 28 #include "minidump/minidump_memory_writer.h" |
27 #include "minidump/minidump_file_writer.h" | 29 #include "minidump/minidump_file_writer.h" |
28 #include "minidump/minidump_thread_id_map.h" | 30 #include "minidump/minidump_thread_id_map.h" |
29 #include "minidump/test/minidump_context_test_util.h" | 31 #include "minidump/test/minidump_context_test_util.h" |
30 #include "minidump/test/minidump_memory_writer_test_util.h" | 32 #include "minidump/test/minidump_memory_writer_test_util.h" |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 } | 522 } |
521 }; | 523 }; |
522 | 524 |
523 template <typename Traits> | 525 template <typename Traits> |
524 void RunInitializeFromSnapshotTest(bool thread_id_collision) { | 526 void RunInitializeFromSnapshotTest(bool thread_id_collision) { |
525 using MinidumpContextType = typename Traits::MinidumpContextType; | 527 using MinidumpContextType = typename Traits::MinidumpContextType; |
526 MINIDUMP_THREAD expect_threads[3] = {}; | 528 MINIDUMP_THREAD expect_threads[3] = {}; |
527 uint64_t thread_ids[arraysize(expect_threads)] = {}; | 529 uint64_t thread_ids[arraysize(expect_threads)] = {}; |
528 uint8_t memory_values[arraysize(expect_threads)] = {}; | 530 uint8_t memory_values[arraysize(expect_threads)] = {}; |
529 uint32_t context_seeds[arraysize(expect_threads)] = {}; | 531 uint32_t context_seeds[arraysize(expect_threads)] = {}; |
| 532 MINIDUMP_MEMORY_DESCRIPTOR tebs[arraysize(expect_threads)] = {}; |
| 533 |
| 534 const size_t kTebSize = 1024; |
530 | 535 |
531 expect_threads[0].ThreadId = 1; | 536 expect_threads[0].ThreadId = 1; |
532 expect_threads[0].SuspendCount = 2; | 537 expect_threads[0].SuspendCount = 2; |
533 expect_threads[0].Priority = 3; | 538 expect_threads[0].Priority = 3; |
534 expect_threads[0].Teb = 0x0123456789abcdef; | 539 expect_threads[0].Teb = 0x0123456789abcdef; |
535 expect_threads[0].Stack.StartOfMemoryRange = 0x1000; | 540 expect_threads[0].Stack.StartOfMemoryRange = 0x1000; |
536 expect_threads[0].Stack.Memory.DataSize = 0x100; | 541 expect_threads[0].Stack.Memory.DataSize = 0x100; |
537 expect_threads[0].ThreadContext.DataSize = sizeof(MinidumpContextType); | 542 expect_threads[0].ThreadContext.DataSize = sizeof(MinidumpContextType); |
538 memory_values[0] = 'A'; | 543 memory_values[0] = 'A'; |
539 context_seeds[0] = 0x80000000; | 544 context_seeds[0] = 0x80000000; |
| 545 tebs[0].StartOfMemoryRange = expect_threads[0].Teb; |
| 546 tebs[0].Memory.DataSize = kTebSize; |
540 | 547 |
541 // The thread at index 1 has no stack. | 548 // The thread at index 1 has no stack. |
542 expect_threads[1].ThreadId = 11; | 549 expect_threads[1].ThreadId = 11; |
543 expect_threads[1].SuspendCount = 12; | 550 expect_threads[1].SuspendCount = 12; |
544 expect_threads[1].Priority = 13; | 551 expect_threads[1].Priority = 13; |
545 expect_threads[1].Teb = 0xfedcba9876543210; | 552 expect_threads[1].Teb = 0xfedcba9876543210; |
546 expect_threads[1].ThreadContext.DataSize = sizeof(MinidumpContextType); | 553 expect_threads[1].ThreadContext.DataSize = sizeof(MinidumpContextType); |
547 context_seeds[1] = 0x40000001; | 554 context_seeds[1] = 0x40000001; |
| 555 tebs[1].StartOfMemoryRange = expect_threads[1].Teb; |
| 556 tebs[1].Memory.DataSize = kTebSize; |
548 | 557 |
549 expect_threads[2].ThreadId = 21; | 558 expect_threads[2].ThreadId = 21; |
550 expect_threads[2].SuspendCount = 22; | 559 expect_threads[2].SuspendCount = 22; |
551 expect_threads[2].Priority = 23; | 560 expect_threads[2].Priority = 23; |
552 expect_threads[2].Teb = 0x1111111111111111; | 561 expect_threads[2].Teb = 0x1111111111111111; |
553 expect_threads[2].Stack.StartOfMemoryRange = 0x3000; | 562 expect_threads[2].Stack.StartOfMemoryRange = 0x3000; |
554 expect_threads[2].Stack.Memory.DataSize = 0x300; | 563 expect_threads[2].Stack.Memory.DataSize = 0x300; |
555 expect_threads[2].ThreadContext.DataSize = sizeof(MinidumpContextType); | 564 expect_threads[2].ThreadContext.DataSize = sizeof(MinidumpContextType); |
556 memory_values[2] = 'd'; | 565 memory_values[2] = 'd'; |
557 context_seeds[2] = 0x20000002; | 566 context_seeds[2] = 0x20000002; |
| 567 tebs[2].StartOfMemoryRange = expect_threads[2].Teb; |
| 568 tebs[2].Memory.DataSize = kTebSize; |
558 | 569 |
559 if (thread_id_collision) { | 570 if (thread_id_collision) { |
560 thread_ids[0] = 0x0123456700000001; | 571 thread_ids[0] = 0x0123456700000001; |
561 thread_ids[1] = 0x89abcdef00000001; | 572 thread_ids[1] = 0x89abcdef00000001; |
562 thread_ids[2] = 4; | 573 thread_ids[2] = 4; |
563 expect_threads[0].ThreadId = 0; | 574 expect_threads[0].ThreadId = 0; |
564 expect_threads[1].ThreadId = 1; | 575 expect_threads[1].ThreadId = 1; |
565 expect_threads[2].ThreadId = 2; | 576 expect_threads[2].ThreadId = 2; |
566 } else { | 577 } else { |
567 thread_ids[0] = 1; | 578 thread_ids[0] = 1; |
(...skipping 20 matching lines...) Expand all Loading... |
588 memory_snapshot->SetAddress( | 599 memory_snapshot->SetAddress( |
589 expect_threads[index].Stack.StartOfMemoryRange); | 600 expect_threads[index].Stack.StartOfMemoryRange); |
590 memory_snapshot->SetSize(expect_threads[index].Stack.Memory.DataSize); | 601 memory_snapshot->SetSize(expect_threads[index].Stack.Memory.DataSize); |
591 memory_snapshot->SetValue(memory_values[index]); | 602 memory_snapshot->SetValue(memory_values[index]); |
592 thread_snapshot->SetStack(memory_snapshot.Pass()); | 603 thread_snapshot->SetStack(memory_snapshot.Pass()); |
593 } | 604 } |
594 | 605 |
595 Traits::InitializeCPUContext(thread_snapshot->MutableContext(), | 606 Traits::InitializeCPUContext(thread_snapshot->MutableContext(), |
596 context_seeds[index]); | 607 context_seeds[index]); |
597 | 608 |
| 609 auto teb_snapshot = make_scoped_ptr(new TestMemorySnapshot()); |
| 610 teb_snapshot->SetAddress(expect_threads[index].Teb); |
| 611 teb_snapshot->SetSize(kTebSize); |
| 612 teb_snapshot->SetValue(static_cast<char>('t' + index)); |
| 613 thread_snapshot->AddExtraMemory(teb_snapshot.Pass()); |
| 614 |
598 thread_snapshots.push_back(thread_snapshot); | 615 thread_snapshots.push_back(thread_snapshot); |
599 } | 616 } |
600 | 617 |
601 auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter()); | 618 auto thread_list_writer = make_scoped_ptr(new MinidumpThreadListWriter()); |
602 auto memory_list_writer = make_scoped_ptr(new MinidumpMemoryListWriter()); | 619 auto memory_list_writer = make_scoped_ptr(new MinidumpMemoryListWriter()); |
603 thread_list_writer->SetMemoryListWriter(memory_list_writer.get()); | 620 thread_list_writer->SetMemoryListWriter(memory_list_writer.get()); |
604 MinidumpThreadIDMap thread_id_map; | 621 MinidumpThreadIDMap thread_id_map; |
605 thread_list_writer->InitializeFromSnapshot(thread_snapshots, &thread_id_map); | 622 thread_list_writer->InitializeFromSnapshot(thread_snapshots, &thread_id_map); |
606 | 623 |
607 MinidumpFileWriter minidump_file_writer; | 624 MinidumpFileWriter minidump_file_writer; |
608 minidump_file_writer.AddStream(thread_list_writer.Pass()); | 625 minidump_file_writer.AddStream(thread_list_writer.Pass()); |
609 minidump_file_writer.AddStream(memory_list_writer.Pass()); | 626 minidump_file_writer.AddStream(memory_list_writer.Pass()); |
610 | 627 |
611 StringFile string_file; | 628 StringFile string_file; |
612 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); | 629 ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file)); |
613 | 630 |
614 const MINIDUMP_THREAD_LIST* thread_list = nullptr; | 631 const MINIDUMP_THREAD_LIST* thread_list = nullptr; |
615 const MINIDUMP_MEMORY_LIST* memory_list = nullptr; | 632 const MINIDUMP_MEMORY_LIST* memory_list = nullptr; |
616 ASSERT_NO_FATAL_FAILURE( | 633 ASSERT_NO_FATAL_FAILURE( |
617 GetThreadListStream(string_file.string(), &thread_list, &memory_list)); | 634 GetThreadListStream(string_file.string(), &thread_list, &memory_list)); |
618 | 635 |
619 ASSERT_EQ(3u, thread_list->NumberOfThreads); | 636 ASSERT_EQ(3u, thread_list->NumberOfThreads); |
620 ASSERT_EQ(2u, memory_list->NumberOfMemoryRanges); | 637 ASSERT_EQ(5u, memory_list->NumberOfMemoryRanges); |
621 | 638 |
622 size_t memory_index = 0; | 639 size_t memory_index = 0; |
623 for (size_t index = 0; index < thread_list->NumberOfThreads; ++index) { | 640 for (size_t index = 0; index < thread_list->NumberOfThreads; ++index) { |
624 SCOPED_TRACE(base::StringPrintf("index %" PRIuS, index)); | 641 SCOPED_TRACE(base::StringPrintf("index %" PRIuS, index)); |
625 | 642 |
626 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack = nullptr; | 643 const MINIDUMP_MEMORY_DESCRIPTOR* observed_stack = nullptr; |
627 const MINIDUMP_MEMORY_DESCRIPTOR** observed_stack_p = | 644 const MINIDUMP_MEMORY_DESCRIPTOR** observed_stack_p = |
628 expect_threads[index].Stack.Memory.DataSize ? &observed_stack : nullptr; | 645 expect_threads[index].Stack.Memory.DataSize ? &observed_stack : nullptr; |
629 const MinidumpContextType* observed_context = nullptr; | 646 const MinidumpContextType* observed_context = nullptr; |
630 ASSERT_NO_FATAL_FAILURE( | 647 ASSERT_NO_FATAL_FAILURE( |
631 ExpectThread(&expect_threads[index], | 648 ExpectThread(&expect_threads[index], |
632 &thread_list->Threads[index], | 649 &thread_list->Threads[index], |
633 string_file.string(), | 650 string_file.string(), |
634 observed_stack_p, | 651 observed_stack_p, |
635 reinterpret_cast<const void**>(&observed_context))); | 652 reinterpret_cast<const void**>(&observed_context))); |
636 | 653 |
637 ASSERT_NO_FATAL_FAILURE(Traits::ExpectMinidumpContext( | 654 ASSERT_NO_FATAL_FAILURE(Traits::ExpectMinidumpContext( |
638 context_seeds[index], observed_context, true)); | 655 context_seeds[index], observed_context, true)); |
639 | 656 |
640 if (observed_stack_p) { | 657 if (observed_stack_p) { |
641 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptorAndContents( | 658 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptorAndContents( |
642 &expect_threads[index].Stack, | 659 &expect_threads[index].Stack, |
643 observed_stack, | 660 observed_stack, |
644 string_file.string(), | 661 string_file.string(), |
645 memory_values[index], | 662 memory_values[index], |
646 index == thread_list->NumberOfThreads - 1)); | 663 false)); |
647 | 664 |
648 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( | 665 ASSERT_NO_FATAL_FAILURE(ExpectMinidumpMemoryDescriptor( |
649 observed_stack, &memory_list->MemoryRanges[memory_index])); | 666 observed_stack, &memory_list->MemoryRanges[memory_index])); |
650 | 667 |
651 ++memory_index; | 668 ++memory_index; |
652 } | 669 } |
653 } | 670 } |
| 671 |
| 672 for (size_t index = 0; index < thread_list->NumberOfThreads; ++index) { |
| 673 const MINIDUMP_MEMORY_DESCRIPTOR* memory = |
| 674 &memory_list->MemoryRanges[memory_index]; |
| 675 ASSERT_NO_FATAL_FAILURE( |
| 676 ExpectMinidumpMemoryDescriptor(&tebs[index], memory)); |
| 677 std::string expected_data(kTebSize, static_cast<char>('t' + index)); |
| 678 std::string observed_data(&string_file.string()[memory->Memory.Rva], |
| 679 memory->Memory.DataSize); |
| 680 EXPECT_EQ(expected_data, observed_data); |
| 681 ++memory_index; |
| 682 } |
654 } | 683 } |
655 | 684 |
656 TEST(MinidumpThreadWriter, InitializeFromSnapshot_x86) { | 685 TEST(MinidumpThreadWriter, InitializeFromSnapshot_x86) { |
657 RunInitializeFromSnapshotTest<InitializeFromSnapshotX86Traits>(false); | 686 RunInitializeFromSnapshotTest<InitializeFromSnapshotX86Traits>(false); |
658 } | 687 } |
659 | 688 |
660 TEST(MinidumpThreadWriter, InitializeFromSnapshot_AMD64) { | 689 TEST(MinidumpThreadWriter, InitializeFromSnapshot_AMD64) { |
661 RunInitializeFromSnapshotTest<InitializeFromSnapshotAMD64Traits>(false); | 690 RunInitializeFromSnapshotTest<InitializeFromSnapshotAMD64Traits>(false); |
662 } | 691 } |
663 | 692 |
(...skipping 17 matching lines...) Expand all Loading... |
681 | 710 |
682 TEST(MinidumpThreadWriterDeathTest, InitializeFromSnapshot_NoContext) { | 711 TEST(MinidumpThreadWriterDeathTest, InitializeFromSnapshot_NoContext) { |
683 ASSERT_DEATH_CHECK( | 712 ASSERT_DEATH_CHECK( |
684 RunInitializeFromSnapshotTest<InitializeFromSnapshotNoContextTraits>( | 713 RunInitializeFromSnapshotTest<InitializeFromSnapshotNoContextTraits>( |
685 false), "context_"); | 714 false), "context_"); |
686 } | 715 } |
687 | 716 |
688 } // namespace | 717 } // namespace |
689 } // namespace test | 718 } // namespace test |
690 } // namespace crashpad | 719 } // namespace crashpad |
OLD | NEW |