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/memory_analyzer.h"
16 :
17 : #include <stdint.h>
18 :
19 : #include <vector>
20 :
21 : #include "base/files/scoped_temp_dir.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(MemoryAnalyzerTest, AnalyzeMinidump) {
34 m : minidump::FileMinidump minidump;
35 m : ASSERT_TRUE(minidump.Open(testing::TestMinidumps::GetNotepad32Dump()));
36 :
37 m : ProcessState process_state;
38 m : SimpleProcessAnalysis analysis(&process_state);
39 m : MemoryAnalyzer analyzer;
40 m : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE, analyzer.Analyze(minidump, analysis));
41 :
42 m : scoped_refptr<ProcessState::Layer<Bytes>> bytes_layer;
43 m : ASSERT_TRUE(process_state.FindLayer(&bytes_layer));
44 m : ASSERT_LE(1, bytes_layer->size());
45 m : }
46 :
47 m : class MemoryAnalyzerSyntheticTest : public testing::SyntheticMinidumpTest {
48 m : protected:
49 m : using MemorySpecification =
50 m : testing::MinidumpSpecification::MemorySpecification;
51 m : using MinidumpSpecification = testing::MinidumpSpecification;
52 :
53 m : static const char kDataFirst[];
54 m : static const char kDataSecond[];
55 m : };
56 :
57 m : const char MemoryAnalyzerSyntheticTest::kDataFirst[] = "ABCD";
58 m : const char MemoryAnalyzerSyntheticTest::kDataSecond[] = "EFGHI";
59 :
60 m : TEST_F(MemoryAnalyzerSyntheticTest, BasicTest) {
61 m : MinidumpSpecification spec;
62 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(80ULL, kDataFirst)));
63 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(88ULL, kDataSecond)));
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 m : MemoryAnalyzer analyzer;
73 m : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE, analyzer.Analyze(minidump, analysis));
74 :
75 : // Validate analysis.
76 m : BytesLayerPtr bytes_layer;
77 m : ASSERT_TRUE(process_state.FindLayer(&bytes_layer));
78 m : EXPECT_EQ(2, bytes_layer->size());
79 :
80 m : std::vector<BytesRecordPtr> matching_records;
81 :
82 : // Retrieve first memory region.
83 m : {
84 m : bytes_layer->GetRecordsAt(80ULL, &matching_records);
85 m : ASSERT_EQ(1, matching_records.size());
86 m : EXPECT_EQ(AddressRange(80ULL, sizeof(kDataFirst) - 1),
87 m : matching_records[0]->range());
88 m : const Bytes& bytes = matching_records[0]->data();
89 m : EXPECT_EQ(kDataFirst, bytes.data());
90 m : }
91 :
92 : // Retrieve second memory region.
93 m : {
94 m : bytes_layer->GetRecordsAt(88ULL, &matching_records);
95 m : ASSERT_EQ(1, matching_records.size());
96 m : EXPECT_EQ(AddressRange(88ULL, sizeof(kDataSecond) - 1),
97 m : matching_records[0]->range());
98 m : const Bytes& bytes = matching_records[0]->data();
99 m : EXPECT_EQ(kDataSecond, bytes.data());
100 m : }
101 m : }
102 :
103 m : TEST_F(MemoryAnalyzerSyntheticTest, OverlappingRangesAreConsolidated) {
104 m : MinidumpSpecification spec(MinidumpSpecification::ALLOW_MEMORY_OVERLAP);
105 :
106 : // Overlap at start.
107 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(84ULL, kDataFirst)));
108 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(86ULL, kDataSecond)));
109 :
110 : // Overlap at end.
111 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(106ULL, kDataFirst)));
112 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(103ULL, kDataSecond)));
113 :
114 : // Overlap at both ends.
115 m : ASSERT_TRUE(
116 m : spec.AddMemoryRegion(MemorySpecification(206ULL, "ABCDEFGHIJKLM")));
117 m : ASSERT_TRUE(spec.AddMemoryRegion(MemorySpecification(209ULL, kDataFirst)));
118 :
119 m : ASSERT_NO_FATAL_FAILURE(Serialize(spec));
120 :
121 : // Analyze.
122 m : minidump::FileMinidump minidump;
123 m : ASSERT_TRUE(minidump.Open(dump_file()));
124 :
125 m : ProcessState process_state;
126 m : SimpleProcessAnalysis analysis(&process_state);
127 m : MemoryAnalyzer analyzer;
128 m : ASSERT_EQ(Analyzer::ANALYSIS_COMPLETE, analyzer.Analyze(minidump, analysis));
129 :
130 : // Validate analysis.
131 m : BytesLayerPtr bytes_layer;
132 m : ASSERT_TRUE(process_state.FindLayer(&bytes_layer));
133 m : EXPECT_EQ(3, bytes_layer->size());
134 :
135 m : std::vector<BytesRecordPtr> matching_records;
136 :
137 : // Retrieve first memory region.
138 m : {
139 m : bytes_layer->GetRecordsAt(84ULL, &matching_records);
140 m : ASSERT_EQ(1, matching_records.size());
141 m : static const char kExpectedData[] = "ABEFGHI";
142 m : EXPECT_EQ(AddressRange(84ULL, sizeof(kExpectedData) - 1),
143 m : matching_records[0]->range());
144 m : const Bytes& bytes = matching_records[0]->data();
145 m : EXPECT_EQ(kExpectedData, bytes.data());
146 m : }
147 :
148 : // Retrieve second memory region.
149 m : {
150 m : bytes_layer->GetRecordsAt(103, &matching_records);
151 m : ASSERT_EQ(1, matching_records.size());
152 m : static const char kExpectedData[] = "EFGHICD";
153 m : EXPECT_EQ(AddressRange(103ULL, sizeof(kExpectedData) - 1),
154 m : matching_records[0]->range());
155 m : const Bytes& bytes = matching_records[0]->data();
156 m : EXPECT_EQ(kExpectedData, bytes.data());
157 m : }
158 :
159 : // Retrieve third memory region.
160 m : {
161 m : bytes_layer->GetRecordsAt(206, &matching_records);
162 m : ASSERT_EQ(1, matching_records.size());
163 m : static const char kExpectedData[] = "ABCABCDHIJKLM";
164 m : EXPECT_EQ(AddressRange(206ULL, sizeof(kExpectedData) - 1),
165 m : matching_records[0]->range());
166 m : const Bytes& bytes = matching_records[0]->data();
167 m : EXPECT_EQ(kExpectedData, bytes.data());
168 m : }
169 m : }
170 :
171 m : } // namespace refinery
|