| // Copyright 2012 Google Inc. All Rights Reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| #include "syzygy/simulate/page_fault_simulation.h" |
| |
| #include "syzygy/core/json_file_writer.h" |
| |
| namespace simulate { |
| |
| PageFaultSimulation::PageFaultSimulation() |
| : fault_count_(0), |
| page_size_(0), |
| pages_per_code_fault_(kDefaultPagesPerCodeFault) { |
| } |
| |
| void PageFaultSimulation::OnProcessStarted(base::Time /*time*/, |
| size_t default_page_size) { |
| // Set the page size if it wasn't set by the user yet. |
| if (page_size_ != 0) |
| return; |
| |
| if (default_page_size != 0) |
| page_size_ = default_page_size; |
| else |
| page_size_ = kDefaultPageSize; |
| |
| LOG(INFO) << "Page size set to " << page_size_; |
| } |
| |
| bool PageFaultSimulation::SerializeToJSON(FILE* output, |
| bool pretty_print) { |
| DCHECK(output != NULL); |
| core::JSONFileWriter json_file(output, pretty_print); |
| |
| // TODO(fixman): Report faulting addresses and times. |
| if (!json_file.OpenDict() || |
| !json_file.OutputKey("page_size") || |
| !json_file.OutputInteger(page_size_) || |
| !json_file.OutputKey("pages_per_code_fault") || |
| !json_file.OutputInteger(pages_per_code_fault_) || |
| !json_file.OutputKey("fault_count") || |
| !json_file.OutputInteger(fault_count_) || |
| !json_file.OutputKey("loaded_pages") || |
| !json_file.OpenList()) { |
| return false; |
| } |
| |
| PageSet::const_iterator i = pages_.begin(); |
| for (; i != pages_.end(); ++i) { |
| if (!json_file.OutputInteger(*i)) { |
| return false; |
| } |
| } |
| |
| if (!json_file.CloseList() || |
| !json_file.CloseDict()) { |
| return false; |
| } |
| |
| DCHECK(json_file.Finished()); |
| return true; |
| } |
| |
| void PageFaultSimulation::OnFunctionEntry(base::Time /*time*/, |
| const Block* block) { |
| DCHECK(block != NULL); |
| DCHECK(page_size_ != 0); |
| |
| const uint32 block_start = block->addr().value(); |
| const uint32 block_size = block->size(); |
| const size_t kStartIndex = block_start / page_size_; |
| const size_t kEndIndex = (block_start + block_size + |
| page_size_ - 1) / page_size_; |
| |
| // Loop through all the pages in the block, and if it isn't already in memory |
| // then simulate a code fault and load all the faulting pages in memory. |
| for (size_t i = kStartIndex; i < kEndIndex; i++) { |
| if (pages_.find(i) == pages_.end()) { |
| fault_count_++; |
| for (size_t j = 0; j < pages_per_code_fault_; j++) { |
| pages_.insert(i + j); |
| } |
| } |
| } |
| } |
| |
| } // namespace simulate |