1 : // Copyright 2015 Google Inc. All Rights Reserved.
2 : //
3 : // Licensed under the Apache License, Version 2.0 (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
6 : //
7 : // http://www.apache.org/licenses/LICENSE-2.0
8 : //
9 : // Unless required by applicable law or agreed to in writing, software
10 : // distributed under the License is distributed on an "AS IS" BASIS,
11 : // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 : // See the License for the specific language governing permissions and
13 : // limitations under the License.
14 :
15 : #include "syzygy/refinery/analyzers/thread_analyzer.h"
16 :
17 : #include <stdint.h>
18 :
19 : #include <vector>
20 :
21 : #include "base/strings/stringprintf.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/minidump/minidump.h"
24 : #include "syzygy/minidump/unittest_util.h"
25 : #include "syzygy/refinery/unittest_util.h"
26 : #include "syzygy/refinery/process_state/process_state.h"
27 : #include "syzygy/refinery/process_state/process_state_util.h"
28 : #include "syzygy/refinery/process_state/refinery.pb.h"
29 :
30 : namespace refinery {
31 :
32 E : TEST(ThreadAnalyzerTest, Basic) {
33 E : minidump::Minidump minidump;
34 E : ASSERT_TRUE(minidump.Open(testing::TestMinidumps::GetNotepad32Dump()));
35 E : ProcessState process_state;
36 :
37 E : ThreadAnalyzer analyzer;
38 : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE,
39 E : analyzer.Analyze(minidump, &process_state));
40 :
41 E : scoped_refptr<ProcessState::Layer<Stack>> stack_layer;
42 E : ASSERT_TRUE(process_state.FindLayer(&stack_layer));
43 :
44 E : ASSERT_LE(1, stack_layer->size());
45 E : }
46 :
47 : class ThreadAnalyzerSyntheticTest : public testing::SyntheticMinidumpTest {
48 : };
49 :
50 E : TEST_F(ThreadAnalyzerSyntheticTest, BasicTest) {
51 E : const size_t kThreadId = 1U;
52 E : const Address kStackAddr = 80ULL;
53 E : const Address kStackSize = 16U;
54 :
55 : // Generate a synthetic minidump with thread information.
56 : testing::MinidumpSpecification::ThreadSpecification thread_spec(
57 E : kThreadId, kStackAddr, kStackSize);
58 E : testing::MinidumpSpecification::MemorySpecification memory_spec;
59 E : thread_spec.FillStackMemorySpecification(&memory_spec);
60 E : testing::MinidumpSpecification spec;
61 E : ASSERT_TRUE(spec.AddMemoryRegion(memory_spec));
62 E : ASSERT_TRUE(spec.AddThread(thread_spec));
63 E : ASSERT_NO_FATAL_FAILURE(Serialize(spec));
64 :
65 : // Analyze.
66 E : minidump::Minidump minidump;
67 E : ASSERT_TRUE(minidump.Open(dump_file()));
68 :
69 E : ProcessState process_state;
70 E : ThreadAnalyzer analyzer;
71 : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE,
72 E : analyzer.Analyze(minidump, &process_state));
73 :
74 : // Validate analysis.
75 E : StackLayerPtr stack_layer;
76 E : ASSERT_TRUE(process_state.FindLayer(&stack_layer));
77 E : ASSERT_EQ(1, stack_layer->size());
78 :
79 E : std::vector<StackRecordPtr> matching_records;
80 E : stack_layer->GetRecordsAt(kStackAddr, &matching_records);
81 E : ASSERT_EQ(1, matching_records.size());
82 : ASSERT_EQ(AddressRange(kStackAddr, kStackSize),
83 E : matching_records[0]->range());
84 E : const Stack& stack = matching_records[0]->data();
85 :
86 E : const ThreadInformation& thread_info = stack.thread_info();
87 : const MINIDUMP_THREAD* thread =
88 E : reinterpret_cast<const MINIDUMP_THREAD*>(&thread_spec.thread_data.at(0));
89 E : ASSERT_EQ(thread->ThreadId, thread_info.thread_id());
90 E : ASSERT_EQ(thread->SuspendCount, thread_info.suspend_count());
91 E : ASSERT_EQ(thread->PriorityClass, thread_info.priority_class());
92 E : ASSERT_EQ(thread->Priority, thread_info.priority());
93 E : ASSERT_EQ(thread->Teb, thread_info.teb_address());
94 :
95 E : const RegisterInformation& reg_info = thread_info.register_info();
96 : const CONTEXT* ctx =
97 E : reinterpret_cast<const CONTEXT*>(&thread_spec.context_data.at(0));
98 E : ASSERT_EQ(ctx->SegGs, reg_info.seg_gs());
99 E : ASSERT_EQ(ctx->SegFs, reg_info.seg_fs());
100 E : ASSERT_EQ(ctx->SegEs, reg_info.seg_es());
101 E : ASSERT_EQ(ctx->SegDs, reg_info.seg_ds());
102 E : ASSERT_EQ(ctx->Edi, reg_info.edi());
103 E : ASSERT_EQ(ctx->Esi, reg_info.esi());
104 E : ASSERT_EQ(ctx->Ebx, reg_info.ebx());
105 E : ASSERT_EQ(ctx->Edx, reg_info.edx());
106 E : ASSERT_EQ(ctx->Ecx, reg_info.ecx());
107 E : ASSERT_EQ(ctx->Eax, reg_info.eax());
108 E : ASSERT_EQ(ctx->Ebp, reg_info.ebp());
109 E : ASSERT_EQ(ctx->Eip, reg_info.eip());
110 E : ASSERT_EQ(ctx->SegCs, reg_info.seg_cs());
111 E : ASSERT_EQ(ctx->EFlags, reg_info.eflags());
112 E : ASSERT_EQ(ctx->Esp, reg_info.esp());
113 E : ASSERT_EQ(ctx->SegSs, reg_info.seg_ss());
114 E : }
115 :
116 : } // namespace refinery
|