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/analyzers/analyzer_util.h"
27 : #include "syzygy/refinery/process_state/process_state.h"
28 : #include "syzygy/refinery/process_state/process_state_util.h"
29 : #include "syzygy/refinery/process_state/refinery.pb.h"
30 :
31 m : namespace refinery {
32 :
33 m : TEST(ThreadAnalyzerTest, Basic) {
34 m : minidump::FileMinidump minidump;
35 m : ASSERT_TRUE(minidump.Open(testing::TestMinidumps::GetNotepad32Dump()));
36 m : ProcessState process_state;
37 m : SimpleProcessAnalysis analysis(&process_state);
38 :
39 m : ThreadAnalyzer analyzer;
40 m : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE, analyzer.Analyze(minidump, analysis));
41 :
42 m : scoped_refptr<ProcessState::Layer<Stack>> stack_layer;
43 m : ASSERT_TRUE(process_state.FindLayer(&stack_layer));
44 :
45 m : ASSERT_LE(1, stack_layer->size());
46 m : }
47 :
48 m : class ThreadAnalyzerSyntheticTest : public testing::SyntheticMinidumpTest {
49 m : };
50 :
51 m : TEST_F(ThreadAnalyzerSyntheticTest, BasicTest) {
52 m : const size_t kThreadId = 1U;
53 m : const Address kStackAddr = 80ULL;
54 m : const Address kStackSize = 16U;
55 :
56 : // Generate a synthetic minidump with thread information.
57 m : testing::MinidumpSpecification::ThreadSpecification thread_spec(
58 m : kThreadId, kStackAddr, kStackSize);
59 m : testing::MinidumpSpecification::MemorySpecification memory_spec;
60 m : thread_spec.FillStackMemorySpecification(&memory_spec);
61 m : testing::MinidumpSpecification spec;
62 m : ASSERT_TRUE(spec.AddMemoryRegion(memory_spec));
63 m : ASSERT_TRUE(spec.AddThread(thread_spec));
64 m : ASSERT_NO_FATAL_FAILURE(Serialize(spec));
65 :
66 : // Analyze.
67 m : minidump::FileMinidump minidump;
68 m : ASSERT_TRUE(minidump.Open(dump_file()));
69 :
70 m : ProcessState process_state;
71 m : SimpleProcessAnalysis analysis(&process_state);
72 :
73 m : ThreadAnalyzer analyzer;
74 m : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE, analyzer.Analyze(minidump, analysis));
75 :
76 : // Validate analysis.
77 m : StackLayerPtr stack_layer;
78 m : ASSERT_TRUE(process_state.FindLayer(&stack_layer));
79 m : ASSERT_EQ(1, stack_layer->size());
80 :
81 m : std::vector<StackRecordPtr> matching_records;
82 m : stack_layer->GetRecordsAt(kStackAddr, &matching_records);
83 m : ASSERT_EQ(1, matching_records.size());
84 m : ASSERT_EQ(AddressRange(kStackAddr, kStackSize),
85 m : matching_records[0]->range());
86 m : const Stack& stack = matching_records[0]->data();
87 :
88 m : const ThreadInformation& thread_info = stack.thread_info();
89 m : const MINIDUMP_THREAD* thread =
90 m : reinterpret_cast<const MINIDUMP_THREAD*>(&thread_spec.thread_data.at(0));
91 m : ASSERT_EQ(thread->ThreadId, thread_info.thread_id());
92 m : ASSERT_EQ(thread->SuspendCount, thread_info.suspend_count());
93 m : ASSERT_EQ(thread->PriorityClass, thread_info.priority_class());
94 m : ASSERT_EQ(thread->Priority, thread_info.priority());
95 m : ASSERT_EQ(thread->Teb, thread_info.teb_address());
96 :
97 m : const RegisterInformation& reg_info = thread_info.register_info();
98 m : const CONTEXT* ctx =
99 m : reinterpret_cast<const CONTEXT*>(&thread_spec.context_data.at(0));
100 m : ASSERT_EQ(ctx->SegGs, reg_info.seg_gs());
101 m : ASSERT_EQ(ctx->SegFs, reg_info.seg_fs());
102 m : ASSERT_EQ(ctx->SegEs, reg_info.seg_es());
103 m : ASSERT_EQ(ctx->SegDs, reg_info.seg_ds());
104 m : ASSERT_EQ(ctx->Edi, reg_info.edi());
105 m : ASSERT_EQ(ctx->Esi, reg_info.esi());
106 m : ASSERT_EQ(ctx->Ebx, reg_info.ebx());
107 m : ASSERT_EQ(ctx->Edx, reg_info.edx());
108 m : ASSERT_EQ(ctx->Ecx, reg_info.ecx());
109 m : ASSERT_EQ(ctx->Eax, reg_info.eax());
110 m : ASSERT_EQ(ctx->Ebp, reg_info.ebp());
111 m : ASSERT_EQ(ctx->Eip, reg_info.eip());
112 m : ASSERT_EQ(ctx->SegCs, reg_info.seg_cs());
113 m : ASSERT_EQ(ctx->EFlags, reg_info.eflags());
114 m : ASSERT_EQ(ctx->Esp, reg_info.esp());
115 m : ASSERT_EQ(ctx->SegSs, reg_info.seg_ss());
116 m : }
117 :
118 m : } // namespace refinery
|