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/playback/playback.h"
16 :
17 : #include <string>
18 :
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/core/unittest_util.h"
22 : #include "syzygy/pdb/omap.h"
23 : #include "syzygy/pe/pe_file.h"
24 : #include "syzygy/pe/unittest_util.h"
25 : #include "syzygy/trace/parse/parse_engine.h"
26 : #include "syzygy/trace/parse/unittest_util.h"
27 : #include "syzygy/version/syzygy_version.h"
28 :
29 : namespace playback {
30 :
31 : namespace {
32 :
33 : using testing::_;
34 : using testing::GetSrcRelativePath;
35 : using testing::GetExeRelativePath;
36 : using testing::GetExeTestDataRelativePath;
37 : using testing::MockParseEventHandler;
38 : using testing::Return;
39 :
40 : // A test parse engine that exposes some internals so we can simulate some
41 : // events.
42 : class TestParseEngine : public trace::parser::ParseEngine {
43 : public:
44 : using trace::parser::ParseEngine::AddModuleInformation;
45 : using trace::parser::ParseEngine::RemoveModuleInformation;
46 : };
47 :
48 : // A test parser that exposes the parse engine, so we can feed it simulated
49 : // events.
50 : class TestParser : public trace::parser::Parser {
51 : public:
52 E : TestParseEngine* active_parse_engine() const {
53 E : return reinterpret_cast<TestParseEngine*>(active_parse_engine_);
54 E : }
55 : };
56 :
57 : class PlaybackTest : public testing::PELibUnitTest {
58 : public:
59 E : PlaybackTest() : image_layout_(&block_graph_) {
60 E : }
61 :
62 E : void SetUp() {
63 : module_path_ =
64 E : GetExeTestDataRelativePath(testing::kTestDllName);
65 :
66 : instrumented_path_ =
67 E : GetExeTestDataRelativePath(testing::kCallTraceInstrumentedTestDllName);
68 :
69 : const base::FilePath kTraceFiles[] = {
70 : GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[0]),
71 : GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[1]),
72 : GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[2]),
73 : GetExeTestDataRelativePath(testing::kCallTraceTraceFiles[3]),
74 E : };
75 : trace_files_ = Playback::TraceFileList(kTraceFiles,
76 E : kTraceFiles + arraysize(kTraceFiles));
77 E : }
78 :
79 E : bool Init() {
80 : playback_.reset(
81 E : new Playback(module_path_, instrumented_path_, trace_files_));
82 :
83 E : parse_event_handler_.reset(new MockParseEventHandler);
84 E : parser_.reset(new TestParser);
85 E : return parser_->Init(parse_event_handler_.get());
86 E : }
87 :
88 : scoped_ptr<Playback> playback_;
89 :
90 : base::FilePath module_path_;
91 : base::FilePath instrumented_path_;
92 : Playback::TraceFileList trace_files_;
93 :
94 : pe::PEFile input_dll_;
95 : block_graph::BlockGraph block_graph_;
96 : pe::ImageLayout image_layout_;
97 :
98 : scoped_ptr<MockParseEventHandler> parse_event_handler_;
99 : scoped_ptr<TestParser> parser_;
100 : };
101 :
102 : } // namespace
103 :
104 E : TEST_F(PlaybackTest, MismatchedDLLTest) {
105 E : module_path_ = GetExeTestDataRelativePath(L"randomized_test_dll.dll");
106 :
107 E : EXPECT_TRUE(Init());
108 E : EXPECT_FALSE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
109 E : }
110 :
111 E : TEST_F(PlaybackTest, BadTraceFile) {
112 : const base::FilePath kTraceFile = GetSrcRelativePath(
113 E : L"syzygy/playback/test_data/bad-trace.bin");
114 E : trace_files_ = Playback::TraceFileList(&kTraceFile, &kTraceFile + 1);
115 :
116 E : EXPECT_TRUE(Init());
117 E : EXPECT_FALSE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
118 E : }
119 :
120 E : TEST_F(PlaybackTest, SuccessfulInit) {
121 E : EXPECT_TRUE(Init());
122 E : EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
123 E : }
124 :
125 E : TEST_F(PlaybackTest, ConsumeCallTraceEvents) {
126 E : EXPECT_TRUE(Init());
127 E : EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
128 :
129 : #ifdef OFFICIAL_BUILD
130 : static const size_t kProcessAttachCount = 4;
131 : static const size_t kBatchFunctionEntryCount = 4;
132 : #else
133 : static const size_t kProcessAttachCount = 12;
134 : static const size_t kBatchFunctionEntryCount = 12;
135 : #endif
136 :
137 E : EXPECT_CALL(*parse_event_handler_, OnProcessStarted(_, _, _)).Times(4);
138 E : EXPECT_CALL(*parse_event_handler_, OnProcessEnded(_, _)).Times(4);
139 E : EXPECT_CALL(*parse_event_handler_, OnFunctionEntry(_, _, _, _)).Times(0);
140 E : EXPECT_CALL(*parse_event_handler_, OnFunctionExit(_, _, _, _)).Times(0);
141 : EXPECT_CALL(*parse_event_handler_, OnBatchFunctionEntry(_, _, _, _)).
142 E : Times(kBatchFunctionEntryCount);
143 : EXPECT_CALL(*parse_event_handler_, OnProcessAttach(_, _, _, _)).
144 E : Times(kProcessAttachCount);
145 E : EXPECT_CALL(*parse_event_handler_, OnThreadAttach(_, _, _, _)).Times(0);
146 E : EXPECT_CALL(*parse_event_handler_, OnThreadDetach(_, _, _, _)).Times(0);
147 : EXPECT_CALL(*parse_event_handler_,
148 E : OnInvocationBatch(_, _, _, _, _)).Times(0);
149 :
150 E : EXPECT_TRUE(parser_->Consume());
151 E : }
152 :
153 E : TEST_F(PlaybackTest, FindFunctionBlock) {
154 E : EXPECT_TRUE(Init());
155 E : EXPECT_TRUE(playback_->Init(&input_dll_, &image_layout_, parser_.get()));
156 :
157 : // Get the instrumented module's signature. We need this so we can inject
158 : // modules into the parse engine.
159 E : pe::PEFile pe_file;
160 E : trace::parser::ModuleInformation module_info;
161 E : ASSERT_TRUE(pe_file.Init(instrumented_path_));
162 E : pe_file.GetSignature(&module_info);
163 :
164 E : const DWORD kPid = 0x1234;
165 :
166 : // Get pointers to text and data.
167 E : const IMAGE_SECTION_HEADER* text = input_dll_.GetSectionHeader(".text");
168 E : const IMAGE_SECTION_HEADER* data = input_dll_.GetSectionHeader(".data");
169 E : ASSERT_TRUE(text != NULL);
170 E : ASSERT_TRUE(data != NULL);
171 : FuncAddr text_addr = reinterpret_cast<FuncAddr>(
172 E : module_info.base_address.value() + text->VirtualAddress);
173 : FuncAddr data_addr = reinterpret_cast<FuncAddr>(
174 E : module_info.base_address.value() + data->VirtualAddress);
175 :
176 E : trace::parser::ModuleInformation other_module_info;
177 E : other_module_info.base_address.set_value(0x3F000000);
178 E : other_module_info.module_size = 0x00010000;
179 E : other_module_info.module_checksum = 0xF000BA55;
180 E : other_module_info.module_time_date_stamp = 0xDEADBEEF;
181 E : other_module_info.path = L"other_module.dll";
182 : FuncAddr other_text_addr = reinterpret_cast<FuncAddr>(
183 E : other_module_info.base_address.value() + 0x1000);
184 :
185 : ASSERT_TRUE(parser_->active_parse_engine()->AddModuleInformation(
186 E : kPid, module_info));
187 :
188 : // We should be able to find text.
189 E : bool error = false;
190 E : EXPECT_TRUE(playback_->FindFunctionBlock(kPid, text_addr, &error) != NULL);
191 E : EXPECT_FALSE(error);
192 :
193 : // We should get an error looking up data.
194 E : error = false;
195 E : EXPECT_TRUE(playback_->FindFunctionBlock(kPid, data_addr, &error) == NULL);
196 E : EXPECT_TRUE(error);
197 :
198 : // We should get an error looking up an address outside of the module.
199 E : error = false;
200 : EXPECT_TRUE(
201 E : playback_->FindFunctionBlock(kPid, other_text_addr, &error) == NULL);
202 E : EXPECT_TRUE(error);
203 :
204 : // Now add the dummy module. Another lookup should succeed but return NULL.
205 : ASSERT_TRUE(parser_->active_parse_engine()->AddModuleInformation(
206 E : kPid, other_module_info));
207 E : error = false;
208 : EXPECT_TRUE(
209 E : playback_->FindFunctionBlock(kPid, other_text_addr, &error) == NULL);
210 E : EXPECT_FALSE(error);
211 E : }
212 :
213 : } // namespace playback
|