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/simulator.h"
16 :
17 : namespace simulate {
18 :
19 : Simulator::Simulator(const base::FilePath& module_path,
20 : const base::FilePath& instrumented_path,
21 : const TraceFileList& trace_files,
22 : SimulationEventHandler* simulation)
23 : : module_path_(module_path),
24 : instrumented_path_(instrumented_path),
25 : trace_files_(trace_files),
26 : simulation_(simulation),
27 : parser_(),
28 : pe_file_(),
29 E : image_layout_(&block_graph_) {
30 E : DCHECK(simulation_ != NULL);
31 E : }
32 :
33 E : bool Simulator::ParseTraceFiles() {
34 E : if (playback_ == NULL) {
35 : playback_.reset(
36 E : new Playback(module_path_, instrumented_path_, trace_files_));
37 : }
38 :
39 E : if (parser_ == NULL) {
40 E : parser_.reset(new Parser());
41 :
42 E : if (!parser_->Init(this)) {
43 i : LOG(ERROR) << "Failed to initialize call trace parser.";
44 : // If we created the object that parser_ refers to, reset the pointer.
45 : // Otherwise we leave it as it was when we found it.
46 i : parser_.reset();
47 i : return false;
48 : }
49 : }
50 :
51 E : if (!playback_->Init(&pe_file_, &image_layout_, parser_.get())) {
52 i : playback_.reset();
53 i : return false;
54 : }
55 :
56 E : if (!parser_->Consume()) {
57 i : playback_.reset();
58 i : return false;
59 : }
60 :
61 E : playback_.reset();
62 :
63 E : return true;
64 E : }
65 :
66 : void Simulator::OnProcessStarted(base::Time time,
67 : DWORD process_id,
68 E : const TraceSystemInfo* data) {
69 : // Call the implementation of OnProcessStarted our simulator uses.
70 E : DCHECK(simulation_ != NULL);
71 :
72 E : if (data == NULL)
73 i : simulation_->OnProcessStarted(time, 0);
74 i : else
75 E : simulation_->OnProcessStarted(time, data->system_info.dwPageSize);
76 E : }
77 :
78 : void Simulator::OnFunctionEntry(base::Time time,
79 : DWORD process_id,
80 : DWORD thread_id,
81 E : const TraceEnterExitEventData* data) {
82 E : DCHECK(playback_ != NULL);
83 E : DCHECK(data != NULL);
84 E : bool error = false;
85 : const BlockGraph::Block* block = playback_->FindFunctionBlock(
86 E : process_id, data->function, &error);
87 :
88 E : if (error) {
89 i : LOG(ERROR) << "Playback::FindFunctionBlock failed.";
90 i : parser_->set_error_occurred(true);
91 i : return;
92 : }
93 :
94 E : if (block == NULL)
95 i : return;
96 :
97 : // Call our simulation with the event data we have.
98 E : DCHECK(simulation_ != NULL);
99 E : simulation_->OnFunctionEntry(time, block);
100 E : }
101 :
102 : void Simulator::OnBatchFunctionEntry(base::Time time,
103 : DWORD process_id,
104 : DWORD thread_id,
105 E : const TraceBatchEnterData* data) {
106 : // Explode the batch event into individual function entry events.
107 E : TraceEnterExitEventData new_data = {};
108 E : for (size_t i = 0; i < data->num_calls; ++i) {
109 E : new_data.function = data->calls[i].function;
110 E : OnFunctionEntry(time, process_id, thread_id, &new_data);
111 E : }
112 E : }
113 :
114 : } // namespace simulate
|