1 : // Copyright 2012 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/simulate/page_fault_simulation.h"
16 :
17 : #include "syzygy/core/json_file_writer.h"
18 :
19 : namespace simulate {
20 :
21 : PageFaultSimulation::PageFaultSimulation()
22 : : fault_count_(0),
23 : page_size_(0),
24 E : pages_per_code_fault_(kDefaultPagesPerCodeFault) {
25 E : }
26 :
27 : void PageFaultSimulation::OnProcessStarted(base::Time /*time*/,
28 E : size_t default_page_size) {
29 : // Set the page size if it wasn't set by the user yet.
30 E : if (page_size_ != 0)
31 i : return;
32 :
33 E : if (default_page_size != 0)
34 E : page_size_ = default_page_size;
35 E : else
36 i : page_size_ = kDefaultPageSize;
37 :
38 E : LOG(INFO) << "Page size set to " << page_size_;
39 E : }
40 :
41 : bool PageFaultSimulation::SerializeToJSON(FILE* output,
42 E : bool pretty_print) {
43 E : DCHECK(output != NULL);
44 E : core::JSONFileWriter json_file(output, pretty_print);
45 :
46 : // TODO(fixman): Report faulting addresses and times.
47 : if (!json_file.OpenDict() ||
48 : !json_file.OutputKey("page_size") ||
49 : !json_file.OutputInteger(page_size_) ||
50 : !json_file.OutputKey("pages_per_code_fault") ||
51 : !json_file.OutputInteger(pages_per_code_fault_) ||
52 : !json_file.OutputKey("fault_count") ||
53 : !json_file.OutputInteger(fault_count_) ||
54 : !json_file.OutputKey("loaded_pages") ||
55 E : !json_file.OpenList()) {
56 i : return false;
57 : }
58 :
59 E : PageSet::const_iterator i = pages_.begin();
60 E : for (; i != pages_.end(); ++i) {
61 E : if (!json_file.OutputInteger(*i)) {
62 i : return false;
63 : }
64 E : }
65 :
66 : if (!json_file.CloseList() ||
67 E : !json_file.CloseDict()) {
68 i : return false;
69 : }
70 :
71 E : DCHECK(json_file.Finished());
72 E : return true;
73 E : }
74 :
75 : void PageFaultSimulation::OnFunctionEntry(base::Time /*time*/,
76 E : const Block* block) {
77 E : DCHECK(block != NULL);
78 E : DCHECK(page_size_ != 0);
79 :
80 E : const uint32 block_start = block->addr().value();
81 E : const uint32 block_size = block->size();
82 E : const size_t kStartIndex = block_start / page_size_;
83 : const size_t kEndIndex = (block_start + block_size +
84 E : page_size_ - 1) / page_size_;
85 :
86 : // Loop through all the pages in the block, and if it isn't already in memory
87 : // then simulate a code fault and load all the faulting pages in memory.
88 E : for (size_t i = kStartIndex; i < kEndIndex; i++) {
89 E : if (pages_.find(i) == pages_.end()) {
90 E : fault_count_++;
91 E : for (size_t j = 0; j < pages_per_code_fault_; j++) {
92 E : pages_.insert(i + j);
93 E : }
94 : }
95 E : }
96 E : }
97 :
98 : } // namespace simulate
|