blob: 4cad968983ab412e18f88d344ae1cc268d7dfb7d [file] [log] [blame]
// 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