| 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 |