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