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/process_state/process_state.h"
16 :
17 : #include <limits>
18 : #include <string>
19 :
20 : #include "base/memory/scoped_ptr.h"
21 : #include "base/strings/string_piece.h"
22 : #include "gtest/gtest.h"
23 : #include "syzygy/refinery/process_state/process_state_util.h"
24 : #include "syzygy/refinery/process_state/refinery.pb.h"
25 :
26 : namespace refinery {
27 :
28 : namespace {
29 :
30 : void ValidateSingleRecordMatch(
31 : AddressRange range,
32 : const std::vector<BytesRecordPtr>& matching_records,
33 E : base::StringPiece testcase) {
34 E : ASSERT_EQ(1, matching_records.size()) << testcase;
35 E : ASSERT_EQ(range, matching_records[0]->range()) << testcase;
36 E : }
37 :
38 : // Adds a stack record to a process state.
39 : void AddStackRecord(const AddressRange& range,
40 : const size_t thread_id,
41 : ProcessState* process_state,
42 E : StackRecordPtr* stack_record) {
43 E : StackLayerPtr stack_layer;
44 E : process_state->FindOrCreateLayer(&stack_layer);
45 E : stack_layer->CreateRecord(range, stack_record);
46 : (*stack_record)
47 : ->mutable_data()
48 : ->mutable_thread_info()
49 E : ->set_thread_id(thread_id);
50 E : }
51 :
52 : } // namespace
53 :
54 E : TEST(ProcessStateTest, FindOrCreateLayer) {
55 E : ProcessState report;
56 :
57 E : scoped_refptr<ProcessState::Layer<Bytes>> bytes_layer;
58 E : EXPECT_FALSE(report.FindLayer(&bytes_layer));
59 E : EXPECT_TRUE(bytes_layer == nullptr);
60 :
61 E : scoped_refptr<ProcessState::Layer<TypedBlock>> typed_layer;
62 E : EXPECT_FALSE(report.FindLayer(&typed_layer));
63 :
64 E : report.FindOrCreateLayer(&bytes_layer);
65 E : EXPECT_TRUE(bytes_layer != nullptr);
66 :
67 E : scoped_refptr<ProcessState::Layer<Bytes>> test_layer;
68 E : EXPECT_TRUE(report.FindLayer(&test_layer));
69 E : EXPECT_EQ(bytes_layer.get(), test_layer.get());
70 :
71 E : EXPECT_FALSE(report.FindLayer(&typed_layer));
72 E : }
73 :
74 E : TEST(ProcessStateTest, FindSingleRecord) {
75 E : const size_t kThreadId = 42;
76 E : const AddressRange kRecordAddressRange(80ULL, 10U);
77 E : ProcessState report;
78 E : StackRecordPtr retrieved;
79 :
80 : // Empty report: returns false.
81 E : ASSERT_FALSE(report.FindSingleRecord(84ULL, &retrieved));
82 :
83 : // Add a stack record to the report.
84 E : StackRecordPtr created;
85 E : AddStackRecord(kRecordAddressRange, kThreadId, &report, &created);
86 :
87 : // Search for address outside record's range.
88 E : ASSERT_FALSE(report.FindSingleRecord(79ULL, &retrieved));
89 E : ASSERT_FALSE(report.FindSingleRecord(90ULL, &retrieved));
90 :
91 : // Search for address within record's range.
92 E : ASSERT_TRUE(report.FindSingleRecord(84ULL, &retrieved));
93 E : ASSERT_EQ(created.get(), retrieved.get());
94 E : }
95 :
96 E : TEST(ProcessStateTest, FindStackRecord) {
97 E : const size_t kThreadId = 42;
98 E : ProcessState report;
99 E : StackRecordPtr retrieved;
100 :
101 : // Report doesn't have a stack layer.
102 E : ASSERT_FALSE(report.FindStackRecord(kThreadId, &retrieved));
103 :
104 : // Report has an empty stack layer.
105 E : StackLayerPtr stack_layer;
106 E : report.FindOrCreateLayer(&stack_layer);
107 E : ASSERT_FALSE(report.FindStackRecord(kThreadId, &retrieved));
108 :
109 : // Add a stack record to the report.
110 E : StackRecordPtr created;
111 E : AddStackRecord(AddressRange(8000ULL, 80U), kThreadId, &report, &created);
112 :
113 : // Search for a non-existing thread id.
114 E : ASSERT_FALSE(report.FindStackRecord(kThreadId + 1, &retrieved));
115 :
116 : // Search for the existing thread id.
117 E : ASSERT_TRUE(report.FindStackRecord(kThreadId, &retrieved));
118 E : ASSERT_EQ(created.get(), retrieved.get());
119 E : }
120 :
121 E : TEST(ProcessStateTest, ExceptionBasics) {
122 E : const int kExceptingThreadId = 1;
123 E : const int kExceptionCode = 2;
124 E : Exception exception;
125 E : exception.set_thread_id(kExceptingThreadId);
126 E : exception.set_exception_code(kExceptionCode);
127 :
128 E : ProcessState state;
129 E : size_t retrieved_thread_id = 0;
130 :
131 : // Retrieving excepting thread id on an empty state fails.
132 E : ASSERT_FALSE(state.GetExceptingThreadId(&retrieved_thread_id));
133 E : retrieved_thread_id = 0;
134 :
135 : // Setting an exception fails when thread isn't in the state.
136 E : ASSERT_FALSE(state.SetException(exception));
137 :
138 : // Add a stack record to the report.
139 E : StackRecordPtr stack_record;
140 : AddStackRecord(AddressRange(8000ULL, 80U), kExceptingThreadId, &state,
141 E : &stack_record);
142 :
143 : // Setting an exception succeeds.
144 E : ASSERT_TRUE(state.SetException(exception));
145 E : ASSERT_TRUE(stack_record->data().thread_info().has_exception());
146 : const Exception& retrieved_exception =
147 E : stack_record->data().thread_info().exception();
148 E : ASSERT_EQ(kExceptingThreadId, retrieved_exception.thread_id());
149 E : ASSERT_EQ(kExceptionCode, retrieved_exception.exception_code());
150 :
151 : // Retrieving the excepting thread id succeeds.
152 E : ASSERT_TRUE(state.GetExceptingThreadId(&retrieved_thread_id));
153 E : ASSERT_EQ(kExceptingThreadId, retrieved_thread_id);
154 :
155 : // Setting a second exception fails.
156 E : ASSERT_FALSE(state.SetException(exception));
157 E : }
158 :
159 E : TEST(ProcessStateTest, AddressRangeBasics) {
160 E : const Address kAddr = 0xCAFE0000ULL;
161 E : const Size kSize = 0xBABEU;
162 :
163 E : AddressRange valid_range(kAddr, kSize);
164 E : ASSERT_TRUE(valid_range.IsValid());
165 E : ASSERT_EQ(kAddr, valid_range.start());
166 E : ASSERT_EQ(kSize, valid_range.size());
167 E : ASSERT_EQ(kAddr, valid_range.start());
168 E : ASSERT_EQ(kAddr, valid_range.start());
169 E : ASSERT_EQ(0xCAFEBABEULL, valid_range.end());
170 :
171 E : AddressRange zero_range(kAddr, 0U);
172 E : ASSERT_FALSE(zero_range.IsValid());
173 :
174 E : AddressRange overflow_range(std::numeric_limits<Address>::max(), 1U);
175 E : ASSERT_FALSE(overflow_range.IsValid());
176 E : }
177 :
178 E : TEST(ProcessStateTest, CreateRecord) {
179 E : ProcessState report;
180 :
181 E : scoped_refptr<ProcessState::Layer<Bytes>> bytes_layer;
182 E : report.FindOrCreateLayer(&bytes_layer);
183 E : EXPECT_TRUE(bytes_layer != nullptr);
184 E : ASSERT_EQ(0, bytes_layer->size());
185 :
186 : // Add a record for a range of memory.
187 E : const Address kAddr = 0xCAFEBABEULL;
188 E : const Size kSize = 0xBABE;
189 E : scoped_refptr<ProcessState::Record<Bytes>> first_record;
190 E : bytes_layer->CreateRecord(AddressRange(kAddr, kSize), &first_record);
191 :
192 E : ASSERT_EQ(AddressRange(kAddr, kSize), first_record->range());
193 E : ASSERT_EQ(1, bytes_layer->size());
194 :
195 : // Add a second record for the same range.
196 E : scoped_refptr<ProcessState::Record<Bytes>> second_record;
197 E : bytes_layer->CreateRecord(AddressRange(kAddr, kSize), &second_record);
198 :
199 E : ASSERT_EQ(AddressRange(kAddr, kSize), second_record->range());
200 E : ASSERT_EQ(2, bytes_layer->size());
201 :
202 : // Verify that this produced two distinct objects.
203 E : ASSERT_NE(first_record.get(), second_record.get());
204 E : }
205 :
206 E : TEST(ProcessStateTest, GetRecordsAt) {
207 : // Create a report with a Bytes layer.
208 E : ProcessState report;
209 E : BytesLayerPtr bytes_layer;
210 E : report.FindOrCreateLayer(&bytes_layer);
211 E : EXPECT_TRUE(bytes_layer != nullptr);
212 E : ASSERT_EQ(0, bytes_layer->size());
213 :
214 : // Add a single record for basic testing.
215 E : BytesRecordPtr record;
216 E : bytes_layer->CreateRecord(AddressRange(80ULL, 16U), &record);
217 :
218 : // Get right before and right after - no match.
219 E : std::vector<BytesRecordPtr> matching_records;
220 E : bytes_layer->GetRecordsAt(79ULL, &matching_records);
221 E : ASSERT_EQ(0, matching_records.size());
222 E : bytes_layer->GetRecordsAt(81ULL, &matching_records);
223 E : ASSERT_EQ(0, matching_records.size());
224 :
225 : // Match.
226 E : bytes_layer->GetRecordsAt(80ULL, &matching_records);
227 E : ASSERT_EQ(1, matching_records.size());
228 E : ASSERT_EQ(record.get(), matching_records[0].get());
229 :
230 : // Add a second record. Match both.
231 E : matching_records.clear();
232 E : bytes_layer->CreateRecord(AddressRange(80ULL, 4U), &record);
233 E : bytes_layer->GetRecordsAt(80ULL, &matching_records);
234 E : ASSERT_EQ(2, matching_records.size());
235 E : }
236 :
237 E : TEST(ProcessStateTest, GetRecordsSpanningSingleRecord) {
238 : // Create a report with a Bytes layer.
239 E : ProcessState report;
240 E : BytesLayerPtr bytes_layer;
241 E : report.FindOrCreateLayer(&bytes_layer);
242 E : EXPECT_TRUE(bytes_layer != nullptr);
243 E : ASSERT_EQ(0, bytes_layer->size());
244 :
245 : // Add a single record for basic testing.
246 E : const Address kAddress = 80ULL;
247 E : const Size kSize = 16U;
248 E : BytesRecordPtr record;
249 E : bytes_layer->CreateRecord(AddressRange(kAddress, kSize), &record);
250 :
251 : // No match: requested region is outside.
252 E : std::vector<BytesRecordPtr> matching_records;
253 : bytes_layer->GetRecordsSpanning(AddressRange(73ULL, 5U),
254 E : &matching_records);
255 E : ASSERT_EQ(0, matching_records.size());
256 : bytes_layer->GetRecordsSpanning(AddressRange(96ULL, 3U),
257 E : &matching_records);
258 E : ASSERT_EQ(0, matching_records.size());
259 :
260 : // No match: requested region straddles.
261 : bytes_layer->GetRecordsSpanning(AddressRange(75ULL, 10U),
262 E : &matching_records);
263 E : ASSERT_EQ(0, matching_records.size());
264 :
265 : // No match: requested region is a superset.
266 : bytes_layer->GetRecordsSpanning(AddressRange(75ULL, 32U),
267 E : &matching_records);
268 E : ASSERT_EQ(0, matching_records.size());
269 :
270 : // Match: requested region is a subset.
271 : bytes_layer->GetRecordsSpanning(AddressRange(84ULL, 4U),
272 E : &matching_records);
273 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
274 E : "Case: Requested region is a subset");
275 E : matching_records.clear();
276 :
277 : // Match: region is exact match.
278 : bytes_layer->GetRecordsSpanning(AddressRange(kAddress, kSize),
279 E : &matching_records);
280 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
281 E : "Case: Requested region is exact match");
282 E : }
283 :
284 E : TEST(ProcessStateTest, GetRecordsSpanningMultipleRecords) {
285 : // Create a report with a Bytes layer.
286 E : ProcessState report;
287 E : BytesLayerPtr bytes_layer;
288 E : report.FindOrCreateLayer(&bytes_layer);
289 E : ASSERT_TRUE(bytes_layer != nullptr);
290 :
291 : // Add a few records (note the 2 records at the same address).
292 E : BytesRecordPtr record;
293 E : bytes_layer->CreateRecord(AddressRange(80ULL, 16U), &record);
294 E : bytes_layer->CreateRecord(AddressRange(75ULL, 25U), &record);
295 E : bytes_layer->CreateRecord(AddressRange(80ULL, 16U), &record);
296 :
297 : // Match a subset.
298 E : std::vector<BytesRecordPtr> matching_records;
299 : bytes_layer->GetRecordsSpanning(AddressRange(82ULL, 4U),
300 E : &matching_records);
301 E : ASSERT_EQ(3, matching_records.size());
302 E : }
303 :
304 E : TEST(ProcessStateTest, GetRecordsIntersectingSingleRecord) {
305 : // Create a report with a Bytes layer.
306 E : ProcessState report;
307 E : BytesLayerPtr bytes_layer;
308 E : report.FindOrCreateLayer(&bytes_layer);
309 E : EXPECT_TRUE(bytes_layer != nullptr);
310 E : ASSERT_EQ(0, bytes_layer->size());
311 :
312 : // Add a single record for basic testing.
313 E : const Address kAddress = 80ULL;
314 E : const Size kSize = 16U;
315 E : BytesRecordPtr record;
316 E : bytes_layer->CreateRecord(AddressRange(kAddress, kSize), &record);
317 :
318 : // No match: requested region is outside.
319 E : std::vector<BytesRecordPtr> matching_records;
320 : bytes_layer->GetRecordsIntersecting(AddressRange(73ULL, 5U),
321 E : &matching_records);
322 E : ASSERT_EQ(0, matching_records.size());
323 : bytes_layer->GetRecordsIntersecting(AddressRange(96ULL, 3U),
324 E : &matching_records);
325 E : ASSERT_EQ(0, matching_records.size());
326 :
327 : // No match: requested region is contiguous.
328 : bytes_layer->GetRecordsIntersecting(AddressRange(75ULL, 5U),
329 E : &matching_records);
330 E : ASSERT_EQ(0, matching_records.size());
331 : bytes_layer->GetRecordsIntersecting(AddressRange(96ULL, 3U),
332 E : &matching_records);
333 E : ASSERT_EQ(0, matching_records.size());
334 :
335 : // Match: requested region straddles.
336 : bytes_layer->GetRecordsIntersecting(AddressRange(75ULL, 10U),
337 E : &matching_records);
338 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
339 E : "Case: Requested region straddles");
340 E : matching_records.clear();
341 :
342 : // Match: requested region is a superset.
343 : bytes_layer->GetRecordsIntersecting(AddressRange(75ULL, 32U),
344 E : &matching_records);
345 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
346 E : "Case: Requested region is a superset");
347 E : matching_records.clear();
348 :
349 : // Match: requested region is a subset.
350 : bytes_layer->GetRecordsIntersecting(AddressRange(84ULL, 4U),
351 E : &matching_records);
352 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
353 E : "Case: Requested region is a subset");
354 E : matching_records.clear();
355 :
356 : // Match: region is exact match.
357 : bytes_layer->GetRecordsIntersecting(AddressRange(kAddress, kSize),
358 E : &matching_records);
359 : ValidateSingleRecordMatch(AddressRange(kAddress, kSize), matching_records,
360 E : "Case: Requested region is an exact match");
361 E : matching_records.clear();
362 E : }
363 :
364 E : TEST(ProcessStateTest, GetRecordsIntersectingMultipleRecords) {
365 : // Create a report with a Bytes layer.
366 E : ProcessState report;
367 E : BytesLayerPtr bytes_layer;
368 E : report.FindOrCreateLayer(&bytes_layer);
369 E : ASSERT_TRUE(bytes_layer != nullptr);
370 :
371 : // Add a few records.
372 E : BytesRecordPtr record;
373 E : bytes_layer->CreateRecord(AddressRange(80ULL, 16U), &record);
374 E : bytes_layer->CreateRecord(AddressRange(75ULL, 25U), &record);
375 : bytes_layer->CreateRecord(AddressRange(80ULL, 16U),
376 E : &record); // Second record at location.
377 :
378 : // Match a subset straddling region.
379 E : std::vector<BytesRecordPtr> matching_records;
380 : bytes_layer->GetRecordsIntersecting(AddressRange(78ULL, 4U),
381 E : &matching_records);
382 E : ASSERT_EQ(3, matching_records.size());
383 E : }
384 :
385 E : TEST(ProcessStateTest, RemoveRecord) {
386 : // Create a report that has a Bytes layer with a single record.
387 E : ProcessState report;
388 E : BytesLayerPtr bytes_layer;
389 E : report.FindOrCreateLayer(&bytes_layer);
390 E : ASSERT_TRUE(bytes_layer != nullptr);
391 :
392 E : const Address kAddress = 80ULL;
393 E : const Size kSize = 16U;
394 E : BytesRecordPtr record;
395 E : bytes_layer->CreateRecord(AddressRange(kAddress, kSize), &record);
396 E : ASSERT_EQ(1, bytes_layer->size());
397 :
398 : // Remove record.
399 E : ASSERT_TRUE(bytes_layer->RemoveRecord(record));
400 E : ASSERT_EQ(0, bytes_layer->size());
401 :
402 : // Removing a second time fails.
403 E : ASSERT_FALSE(bytes_layer->RemoveRecord(record));
404 E : }
405 :
406 E : TEST(ProcessStateTest, LayerIteration) {
407 : // Create a report that has a Bytes layer with few records.
408 E : ProcessState report;
409 E : BytesLayerPtr bytes_layer;
410 E : report.FindOrCreateLayer(&bytes_layer);
411 E : ASSERT_TRUE(bytes_layer != nullptr);
412 :
413 E : BytesRecordPtr record;
414 E : bytes_layer->CreateRecord(AddressRange(80ULL, 4U), &record);
415 E : bytes_layer->CreateRecord(AddressRange(84ULL, 4U), &record);
416 E : bytes_layer->CreateRecord(AddressRange(88ULL, 4U), &record);
417 :
418 : // Manual iteration.
419 : // Note: for ease of testing, this test relies on the iterator returning
420 : // records by ascending address. However, this is not in the contract.
421 E : ProcessState::Layer<Bytes>::Iterator it = bytes_layer->begin();
422 E : ASSERT_EQ(80ULL, (*it)->range().start());
423 E : ++it;
424 E : ASSERT_EQ(84ULL, (*it)->range().start());
425 E : ++it;
426 E : ASSERT_EQ(88ULL, (*it)->range().start());
427 E : ++it;
428 E : ASSERT_EQ(bytes_layer->end(), it);
429 :
430 : // Range based for loop.
431 E : int record_count = 0;
432 E : for (BytesRecordPtr rec : *bytes_layer) {
433 E : ++record_count;
434 E : }
435 E : ASSERT_EQ(3, record_count);
436 E : }
437 :
438 : class ProcessStateBitSourceTest : public testing::Test {
439 : protected:
440 E : void SetUp() override {
441 : // Populate the process state with a single Bytes record at address_,
442 : // containing data_.
443 :
444 E : address_ = 80ULL;
445 E : data_ = "0123456789";
446 :
447 : // Note: range doesn't include trailing '\0'.
448 E : AddressRange record_range(address_, data_.size());
449 :
450 E : BytesLayerPtr bytes_layer;
451 E : process_state_.FindOrCreateLayer(&bytes_layer);
452 E : BytesRecordPtr bytes_record;
453 E : bytes_layer->CreateRecord(record_range, &bytes_record);
454 E : *bytes_record->mutable_data()->mutable_data() = data_;
455 E : }
456 :
457 E : Address address() { return address_; }
458 E : const std::string& data() { return data_; }
459 :
460 : void PerformGetFromTest(AddressRange requested,
461 : size_t expected_cnt,
462 : bool bytes_requested,
463 E : const std::string& expected_bytes) {
464 E : size_t retrieved_cnt = 0U;
465 E : scoped_ptr<char> buffer(new char[data().size()]);
466 E : memset(buffer.get(), 0, data().size());
467 :
468 E : ASSERT_TRUE(
469 : process_state_.GetFrom(requested, &retrieved_cnt, buffer.get()));
470 :
471 E : ASSERT_EQ(expected_cnt, retrieved_cnt);
472 E : if (bytes_requested)
473 E : ASSERT_EQ(expected_bytes, std::string(buffer.get(), retrieved_cnt));
474 E : }
475 :
476 : ProcessState process_state_;
477 :
478 : private:
479 : Address address_;
480 : std::string data_;
481 : };
482 :
483 E : TEST_F(ProcessStateBitSourceTest, GetAll) {
484 E : char retrieved = '-';
485 :
486 : // Fail to retrieve data that is not fully in the process state.
487 E : AddressRange desired_range = AddressRange(address() - 1, data().size());
488 E : ASSERT_FALSE(process_state_.GetAll(desired_range, &retrieved));
489 :
490 : // Successfully retrieve data that is in the process state.
491 E : retrieved = '-';
492 E : ASSERT_TRUE(process_state_.GetAll(AddressRange(address(), 1U), &retrieved));
493 E : ASSERT_EQ(data()[0], retrieved);
494 E : }
495 :
496 E : TEST_F(ProcessStateBitSourceTest, GetFrom) {
497 E : size_t retrieved_cnt = 0U;
498 E : scoped_ptr<char> buffer(new char[data().size()]);
499 :
500 : // Fail to retrieve when the head is outside existing data.
501 E : AddressRange desired(address() - 1U, data().size());
502 E : ASSERT_FALSE(process_state_.GetFrom(desired, &retrieved_cnt, nullptr));
503 E : desired = AddressRange(address() + data().size(), 1U);
504 E : ASSERT_FALSE(process_state_.GetFrom(desired, &retrieved_cnt, buffer.get()));
505 :
506 : // Successful full retrieval - not asking for data.
507 E : desired = AddressRange(address() + 1, data().size() - 1);
508 E : PerformGetFromTest(desired, data().size() - 1, false, "");
509 :
510 : // Successful partial retrieval - not asking for data.
511 E : desired = AddressRange(address() + 1, data().size());
512 E : PerformGetFromTest(desired, data().size() - 1, false, "");
513 :
514 : // Successful full retrieval - asking for data.
515 E : std::string expected_bytes = data().substr(1, data().size() - 1);
516 E : desired = AddressRange(address() + 1, data().size() - 1);
517 E : PerformGetFromTest(desired, data().size() - 1, true, expected_bytes);
518 :
519 : // Successful partial retrieval - asking for data.
520 E : desired = AddressRange(address() + 1, data().size());
521 E : PerformGetFromTest(desired, data().size() - 1, true, expected_bytes);
522 E : }
523 :
524 : } // namespace refinery
|