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/instrument/instrument_app.h"
16 :
17 : #include "base/environment.h"
18 : #include "base/stringprintf.h"
19 : #include "gmock/gmock.h"
20 : #include "gtest/gtest.h"
21 : #include "syzygy/block_graph/unittest_util.h"
22 : #include "syzygy/common/unittest_util.h"
23 : #include "syzygy/core/unittest_util.h"
24 : #include "syzygy/pe/image_filter.h"
25 : #include "syzygy/pe/pe_relinker.h"
26 : #include "syzygy/pe/pe_utils.h"
27 : #include "syzygy/pe/unittest_util.h"
28 : #include "syzygy/trace/protocol/call_trace_defs.h"
29 :
30 : namespace instrument {
31 :
32 : namespace {
33 :
34 : using testing::StrictMock;
35 : using testing::Return;
36 : using testing::_;
37 :
38 : class MockRelinker : public pe::PERelinker {
39 : public:
40 E : MOCK_METHOD0(Init, bool());
41 E : MOCK_METHOD0(Relink, bool());
42 : };
43 :
44 : class TestInstrumentApp : public InstrumentApp {
45 : public:
46 : using InstrumentApp::input_dll_path_;
47 : using InstrumentApp::input_pdb_path_;
48 : using InstrumentApp::output_dll_path_;
49 : using InstrumentApp::output_pdb_path_;
50 : using InstrumentApp::filter_path_;
51 : using InstrumentApp::client_dll_;
52 : using InstrumentApp::allow_overwrite_;
53 : using InstrumentApp::new_decomposer_;
54 : using InstrumentApp::no_augment_pdb_;
55 : using InstrumentApp::no_parse_debug_info_;
56 : using InstrumentApp::no_strip_strings_;
57 : using InstrumentApp::debug_friendly_;
58 : using InstrumentApp::instrument_unsafe_references_;
59 : using InstrumentApp::module_entry_only_;
60 : using InstrumentApp::thunk_imports_;
61 : using InstrumentApp::mode_;
62 :
63 E : pe::PERelinker& GetRelinker() OVERRIDE {
64 E : return mock_relinker_;
65 E : }
66 :
67 : StrictMock<MockRelinker> mock_relinker_;
68 : };
69 :
70 : typedef common::Application<TestInstrumentApp> TestApp;
71 :
72 : class InstrumentAppTest : public testing::PELibUnitTest {
73 : public:
74 : typedef testing::PELibUnitTest Super;
75 :
76 : InstrumentAppTest()
77 : : cmd_line_(FilePath(L"instrument.exe")),
78 E : test_impl_(test_app_.implementation()) {
79 E : }
80 :
81 E : void SetUp() {
82 E : Super::SetUp();
83 :
84 : // Several of the tests generate progress and (deliberate) error messages
85 : // that would otherwise clutter the unittest output.
86 E : logging::SetMinLogLevel(logging::LOG_FATAL);
87 :
88 : // Setup the IO streams.
89 E : CreateTemporaryDir(&temp_dir_);
90 E : stdin_path_ = temp_dir_.Append(L"NUL");
91 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
92 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
93 E : InitStreams(stdin_path_, stdout_path_, stderr_path_);
94 :
95 : // Initialize the (potential) input and output path values.
96 E : abs_input_dll_path_ = testing::GetExeRelativePath(testing::kTestDllName);
97 E : input_dll_path_ = testing::GetRelativePath(abs_input_dll_path_);
98 E : abs_input_pdb_path_ = testing::GetExeRelativePath(testing::kTestDllPdbName);
99 E : input_pdb_path_ = testing::GetRelativePath(abs_input_pdb_path_);
100 E : output_dll_path_ = temp_dir_.Append(input_dll_path_.BaseName());
101 E : output_pdb_path_ = temp_dir_.Append(input_pdb_path_.BaseName());
102 E : test_dll_filter_path_ = temp_dir_.Append(L"test_dll_filter.json");
103 E : dummy_filter_path_ = temp_dir_.Append(L"dummy_filter.json");
104 :
105 E : ASSERT_NO_FATAL_FAILURE(ConfigureTestApp(&test_app_));
106 E : }
107 :
108 E : void MakeFilters() {
109 : // Create a valid test_dll filter. Just so it's not empty we mark the NT
110 : // headers as non-instrumentable.
111 E : pe::ImageFilter filter;
112 E : ASSERT_TRUE(filter.Init(abs_input_dll_path_));
113 : filter.filter.Mark(pe::ImageFilter::RelativeAddressFilter::Range(
114 E : core::RelativeAddress(0), 4096));
115 E : ASSERT_TRUE(filter.SaveToJSON(false, test_dll_filter_path_));
116 :
117 : // Muck up the time date stamp and create an invalid filter.
118 E : filter.signature.module_time_date_stamp ^= 0x0F00BA55;
119 E : ASSERT_TRUE(filter.SaveToJSON(true, dummy_filter_path_));
120 E : }
121 :
122 : // Points the application at the fixture's command-line and IO streams.
123 : template<typename TestAppType>
124 E : void ConfigureTestApp(TestAppType* test_app) {
125 E : test_app->set_command_line(&cmd_line_);
126 E : test_app->set_in(in());
127 E : test_app->set_out(out());
128 E : test_app->set_err(err());
129 E : }
130 :
131 : // Runs an instrumentation pass in the given mode and validates that the
132 : // resulting output DLL loads.
133 E : void EndToEndTest(const std::string& mode) {
134 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
135 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
136 E : cmd_line_.AppendSwitchASCII("mode", mode);
137 :
138 : // Create the instrumented DLL.
139 E : common::Application<instrument::InstrumentApp> app;
140 E : ASSERT_NO_FATAL_FAILURE(ConfigureTestApp(&app));
141 E : ASSERT_EQ(0, app.Run());
142 :
143 : // Make it non-mandatory that there be a trace service running.
144 E : scoped_ptr<base::Environment> env(base::Environment::Create());
145 E : std::string env_var;
146 : env->SetVar(
147 : ::kSyzygyRpcSessionMandatoryEnvVar,
148 : base::StringPrintf("%s,0;%s,0;%s,0;%s,0",
149 : InstrumentApp::kCallTraceClientDllBasicBlockEntry,
150 : InstrumentApp::kCallTraceClientDllCoverage,
151 : InstrumentApp::kCallTraceClientDllProfile,
152 E : InstrumentApp::kCallTraceClientDllRpc));
153 :
154 : // Validate that the test dll loads post instrumentation.
155 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_dll_path_));
156 E : }
157 :
158 : // Stashes the current log-level before each test instance and restores it
159 : // after each test completes.
160 : testing::ScopedLogLevelSaver log_level_saver;
161 :
162 : // @name The application under test.
163 : // @{
164 : TestApp test_app_;
165 : TestApp::Implementation& test_impl_;
166 : FilePath temp_dir_;
167 : FilePath stdin_path_;
168 : FilePath stdout_path_;
169 : FilePath stderr_path_;
170 : // @}
171 :
172 : // @name Command-line and parameters.
173 : // @{
174 : CommandLine cmd_line_;
175 : FilePath input_dll_path_;
176 : FilePath input_pdb_path_;
177 : FilePath output_dll_path_;
178 : FilePath output_pdb_path_;
179 : FilePath test_dll_filter_path_;
180 : FilePath dummy_filter_path_;
181 : // @}
182 :
183 : // @name Expected final values of input parameters.
184 : // @{
185 : FilePath abs_input_dll_path_;
186 : FilePath abs_input_pdb_path_;
187 : // @}
188 : };
189 :
190 : } // namespace
191 :
192 E : TEST_F(InstrumentAppTest, GetHelp) {
193 E : cmd_line_.AppendSwitch("help");
194 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
195 E : }
196 :
197 E : TEST_F(InstrumentAppTest, EmptyCommandLineFails) {
198 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
199 E : }
200 :
201 E : TEST_F(InstrumentAppTest, ParseWithNoInputImageFails) {
202 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
203 :
204 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
205 E : }
206 :
207 E : TEST_F(InstrumentAppTest, ParseWithNoOutputImageFails) {
208 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
209 :
210 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
211 E : }
212 :
213 E : TEST_F(InstrumentAppTest, ParseMinimalAsan) {
214 E : cmd_line_.AppendSwitchASCII("mode", "asan");
215 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
216 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
217 :
218 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
219 :
220 E : EXPECT_EQ(InstrumentApp::kInstrumentAsanMode, test_impl_.mode_);
221 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
222 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
223 E : EXPECT_TRUE(test_impl_.client_dll_.empty());
224 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
225 E : EXPECT_FALSE(test_impl_.new_decomposer_);
226 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
227 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
228 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
229 E : EXPECT_FALSE(test_impl_.debug_friendly_);
230 E : }
231 :
232 E : TEST_F(InstrumentAppTest, ParseFullAsan) {
233 E : cmd_line_.AppendSwitchASCII("mode", "asan");
234 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
235 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
236 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
237 E : cmd_line_.AppendSwitchASCII("agent", "foo.dll");
238 E : cmd_line_.AppendSwitch("debug-friendly");
239 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
240 E : cmd_line_.AppendSwitch("new-decomposer");
241 E : cmd_line_.AppendSwitch("no-augment-pdb");
242 E : cmd_line_.AppendSwitch("no-parse-debug-info");
243 E : cmd_line_.AppendSwitch("no-strip-strings");
244 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
245 E : cmd_line_.AppendSwitch("overwrite");
246 :
247 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
248 :
249 E : EXPECT_EQ(InstrumentApp::kInstrumentAsanMode, test_impl_.mode_);
250 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
251 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
252 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
253 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
254 E : EXPECT_EQ(test_dll_filter_path_, test_impl_.filter_path_);
255 E : EXPECT_TRUE(test_impl_.client_dll_.empty());
256 E : EXPECT_TRUE(test_impl_.allow_overwrite_);
257 E : EXPECT_TRUE(test_impl_.new_decomposer_);
258 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
259 E : EXPECT_TRUE(test_impl_.no_parse_debug_info_);
260 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
261 E : EXPECT_TRUE(test_impl_.debug_friendly_);
262 E : }
263 :
264 E : TEST_F(InstrumentAppTest, ParseMinimalBasicBlockEntry) {
265 E : cmd_line_.AppendSwitchASCII("mode", "bbentry");
266 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
267 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
268 :
269 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
270 :
271 E : EXPECT_EQ(InstrumentApp::kInstrumentBasicBlockEntryMode, test_impl_.mode_);
272 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
273 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
274 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllBasicBlockEntry),
275 E : test_impl_.client_dll_);
276 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
277 E : EXPECT_FALSE(test_impl_.new_decomposer_);
278 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
279 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
280 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
281 E : EXPECT_FALSE(test_impl_.debug_friendly_);
282 E : }
283 :
284 E : TEST_F(InstrumentAppTest, ParseFullBasicBlockEntry) {
285 E : cmd_line_.AppendSwitchASCII("mode", "bbentry");
286 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
287 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
288 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
289 E : cmd_line_.AppendSwitchASCII("agent", "foo.dll");
290 E : cmd_line_.AppendSwitch("debug-friendly");
291 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
292 E : cmd_line_.AppendSwitch("new-decomposer");
293 E : cmd_line_.AppendSwitch("no-augment-pdb");
294 E : cmd_line_.AppendSwitch("no-parse-debug-info");
295 E : cmd_line_.AppendSwitch("no-strip-strings");
296 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
297 E : cmd_line_.AppendSwitch("overwrite");
298 :
299 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
300 :
301 E : EXPECT_EQ(InstrumentApp::kInstrumentBasicBlockEntryMode, test_impl_.mode_);
302 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
303 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
304 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
305 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
306 E : EXPECT_EQ(test_dll_filter_path_, test_impl_.filter_path_);
307 E : EXPECT_EQ(std::string("foo.dll"), test_impl_.client_dll_);
308 E : EXPECT_TRUE(test_impl_.allow_overwrite_);
309 E : EXPECT_TRUE(test_impl_.new_decomposer_);
310 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
311 E : EXPECT_TRUE(test_impl_.no_parse_debug_info_);
312 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
313 E : EXPECT_TRUE(test_impl_.debug_friendly_);
314 E : }
315 :
316 E : TEST_F(InstrumentAppTest, ParseMinimalCallTrace) {
317 E : cmd_line_.AppendSwitchASCII("mode", "calltrace");
318 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
319 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
320 :
321 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
322 :
323 E : EXPECT_EQ(InstrumentApp::kInstrumentCallTraceMode, test_impl_.mode_);
324 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
325 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
326 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllRpc),
327 E : test_impl_.client_dll_);
328 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
329 E : EXPECT_FALSE(test_impl_.new_decomposer_);
330 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
331 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
332 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
333 E : EXPECT_FALSE(test_impl_.debug_friendly_);
334 E : EXPECT_FALSE(test_impl_.thunk_imports_);
335 E : EXPECT_TRUE(test_impl_.instrument_unsafe_references_);
336 E : EXPECT_FALSE(test_impl_.module_entry_only_);
337 E : }
338 :
339 E : TEST_F(InstrumentAppTest, ParseFullCallTrace) {
340 E : cmd_line_.AppendSwitchASCII("mode", "calltrace");
341 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
342 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
343 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
344 E : cmd_line_.AppendSwitchASCII("agent", "foo.dll");
345 E : cmd_line_.AppendSwitch("debug-friendly");
346 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
347 E : cmd_line_.AppendSwitch("new-decomposer");
348 E : cmd_line_.AppendSwitch("no-augment-pdb");
349 E : cmd_line_.AppendSwitch("no-parse-debug-info");
350 E : cmd_line_.AppendSwitch("no-strip-strings");
351 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
352 E : cmd_line_.AppendSwitch("overwrite");
353 E : cmd_line_.AppendSwitch("instrument-imports");
354 E : cmd_line_.AppendSwitch("module-entry-only");
355 E : cmd_line_.AppendSwitch("no-unsafe-refs");
356 :
357 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
358 :
359 E : EXPECT_EQ(InstrumentApp::kInstrumentCallTraceMode, test_impl_.mode_);
360 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
361 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
362 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
363 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
364 E : EXPECT_EQ(test_dll_filter_path_, test_impl_.filter_path_);
365 E : EXPECT_EQ(std::string("foo.dll"), test_impl_.client_dll_);
366 E : EXPECT_TRUE(test_impl_.allow_overwrite_);
367 E : EXPECT_TRUE(test_impl_.new_decomposer_);
368 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
369 E : EXPECT_TRUE(test_impl_.no_parse_debug_info_);
370 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
371 E : EXPECT_TRUE(test_impl_.debug_friendly_);
372 E : EXPECT_TRUE(test_impl_.thunk_imports_);
373 E : EXPECT_FALSE(test_impl_.instrument_unsafe_references_);
374 E : EXPECT_TRUE(test_impl_.module_entry_only_);
375 E : }
376 :
377 E : TEST_F(InstrumentAppTest, ParseMinimalCoverage) {
378 E : cmd_line_.AppendSwitchASCII("mode", "coverage");
379 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
380 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
381 :
382 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
383 :
384 E : EXPECT_EQ(InstrumentApp::kInstrumentCoverageMode, test_impl_.mode_);
385 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
386 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
387 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllCoverage),
388 E : test_impl_.client_dll_);
389 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
390 E : EXPECT_FALSE(test_impl_.new_decomposer_);
391 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
392 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
393 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
394 E : EXPECT_FALSE(test_impl_.debug_friendly_);
395 E : }
396 :
397 E : TEST_F(InstrumentAppTest, ParseFullCoverage) {
398 E : cmd_line_.AppendSwitchASCII("mode", "coverage");
399 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
400 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
401 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
402 E : cmd_line_.AppendSwitchASCII("agent", "foo.dll");
403 E : cmd_line_.AppendSwitch("debug-friendly");
404 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
405 E : cmd_line_.AppendSwitch("new-decomposer");
406 E : cmd_line_.AppendSwitch("no-augment-pdb");
407 E : cmd_line_.AppendSwitch("no-parse-debug-info");
408 E : cmd_line_.AppendSwitch("no-strip-strings");
409 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
410 E : cmd_line_.AppendSwitch("overwrite");
411 :
412 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
413 :
414 E : EXPECT_EQ(InstrumentApp::kInstrumentCoverageMode, test_impl_.mode_);
415 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
416 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
417 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
418 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
419 E : EXPECT_EQ(test_dll_filter_path_, test_impl_.filter_path_);
420 E : EXPECT_EQ(std::string("foo.dll"), test_impl_.client_dll_);
421 E : EXPECT_TRUE(test_impl_.allow_overwrite_);
422 E : EXPECT_TRUE(test_impl_.new_decomposer_);
423 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
424 E : EXPECT_TRUE(test_impl_.no_parse_debug_info_);
425 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
426 E : EXPECT_TRUE(test_impl_.debug_friendly_);
427 E : }
428 :
429 E : TEST_F(InstrumentAppTest, ParseMinimalProfile) {
430 E : cmd_line_.AppendSwitchASCII("mode", "profile");
431 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
432 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
433 :
434 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
435 E : EXPECT_EQ(InstrumentApp::kInstrumentProfileMode, test_impl_.mode_);
436 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
437 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
438 :
439 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllProfile),
440 E : test_impl_.client_dll_);
441 :
442 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
443 E : EXPECT_FALSE(test_impl_.new_decomposer_);
444 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
445 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
446 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
447 E : EXPECT_FALSE(test_impl_.debug_friendly_);
448 E : EXPECT_FALSE(test_impl_.thunk_imports_);
449 E : EXPECT_FALSE(test_impl_.instrument_unsafe_references_);
450 E : EXPECT_FALSE(test_impl_.module_entry_only_);
451 E : }
452 :
453 E : TEST_F(InstrumentAppTest, ParseFullProfile) {
454 E : cmd_line_.AppendSwitchASCII("mode", "profile");
455 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
456 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
457 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
458 E : cmd_line_.AppendSwitchASCII("agent", "foo.dll");
459 E : cmd_line_.AppendSwitch("debug-friendly");
460 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
461 E : cmd_line_.AppendSwitch("new-decomposer");
462 E : cmd_line_.AppendSwitch("no-augment-pdb");
463 E : cmd_line_.AppendSwitch("no-parse-debug-info");
464 E : cmd_line_.AppendSwitch("no-strip-strings");
465 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
466 E : cmd_line_.AppendSwitch("overwrite");
467 E : cmd_line_.AppendSwitch("instrument-imports");
468 :
469 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
470 :
471 E : EXPECT_EQ(InstrumentApp::kInstrumentProfileMode, test_impl_.mode_);
472 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
473 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
474 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
475 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
476 E : EXPECT_EQ(test_dll_filter_path_, test_impl_.filter_path_);
477 E : EXPECT_EQ(std::string("foo.dll"), test_impl_.client_dll_);
478 E : EXPECT_TRUE(test_impl_.allow_overwrite_);
479 E : EXPECT_TRUE(test_impl_.new_decomposer_);
480 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
481 E : EXPECT_TRUE(test_impl_.no_parse_debug_info_);
482 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
483 E : EXPECT_TRUE(test_impl_.debug_friendly_);
484 E : EXPECT_TRUE(test_impl_.thunk_imports_);
485 E : }
486 :
487 E : TEST_F(InstrumentAppTest, DeprecatedParseNoModeSpecifyDlls) {
488 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
489 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
490 :
491 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
492 E : EXPECT_EQ(InstrumentApp::kInstrumentCallTraceMode, test_impl_.mode_);
493 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
494 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
495 :
496 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllRpc),
497 E : test_impl_.client_dll_);
498 :
499 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
500 E : EXPECT_FALSE(test_impl_.new_decomposer_);
501 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
502 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
503 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
504 E : EXPECT_FALSE(test_impl_.debug_friendly_);
505 E : EXPECT_FALSE(test_impl_.thunk_imports_);
506 E : EXPECT_TRUE(test_impl_.instrument_unsafe_references_);
507 E : EXPECT_FALSE(test_impl_.module_entry_only_);
508 E : }
509 :
510 E : TEST_F(InstrumentAppTest, DeprecatedParseCallTraceClientRpc) {
511 E : cmd_line_.AppendSwitchASCII("call-trace-client", "RPC");
512 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
513 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
514 :
515 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
516 E : EXPECT_EQ(InstrumentApp::kInstrumentCallTraceMode, test_impl_.mode_);
517 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
518 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
519 :
520 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllRpc),
521 E : test_impl_.client_dll_);
522 :
523 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
524 E : EXPECT_FALSE(test_impl_.new_decomposer_);
525 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
526 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
527 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
528 E : EXPECT_FALSE(test_impl_.debug_friendly_);
529 E : EXPECT_FALSE(test_impl_.thunk_imports_);
530 E : EXPECT_TRUE(test_impl_.instrument_unsafe_references_);
531 E : EXPECT_FALSE(test_impl_.module_entry_only_);
532 E : }
533 :
534 E : TEST_F(InstrumentAppTest, DeprecatedParseCallTraceClientProfiler) {
535 E : cmd_line_.AppendSwitchASCII("call-trace-client", "profiler");
536 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
537 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
538 :
539 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
540 E : EXPECT_EQ(InstrumentApp::kInstrumentProfileMode, test_impl_.mode_);
541 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
542 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
543 :
544 : EXPECT_EQ(std::string(InstrumentApp::kCallTraceClientDllProfile),
545 E : test_impl_.client_dll_);
546 :
547 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
548 E : EXPECT_FALSE(test_impl_.new_decomposer_);
549 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
550 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
551 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
552 E : EXPECT_FALSE(test_impl_.debug_friendly_);
553 E : EXPECT_FALSE(test_impl_.thunk_imports_);
554 E : EXPECT_FALSE(test_impl_.instrument_unsafe_references_);
555 E : EXPECT_FALSE(test_impl_.module_entry_only_);
556 E : }
557 :
558 E : TEST_F(InstrumentAppTest, DeprecatedParseCallTraceClientOtherDll) {
559 E : cmd_line_.AppendSwitchASCII("call-trace-client", "foo.dll");
560 E : cmd_line_.AppendSwitchPath("input-dll", input_dll_path_);
561 E : cmd_line_.AppendSwitchPath("output-dll", output_dll_path_);
562 :
563 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
564 E : EXPECT_EQ(InstrumentApp::kInstrumentCallTraceMode, test_impl_.mode_);
565 E : EXPECT_EQ(abs_input_dll_path_, test_impl_.input_dll_path_);
566 E : EXPECT_EQ(output_dll_path_, test_impl_.output_dll_path_);
567 :
568 : EXPECT_EQ(std::string("foo.dll"),
569 E : test_impl_.client_dll_);
570 :
571 E : EXPECT_FALSE(test_impl_.allow_overwrite_);
572 E : EXPECT_FALSE(test_impl_.new_decomposer_);
573 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
574 E : EXPECT_FALSE(test_impl_.no_parse_debug_info_);
575 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
576 E : EXPECT_FALSE(test_impl_.debug_friendly_);
577 E : EXPECT_FALSE(test_impl_.thunk_imports_);
578 E : EXPECT_TRUE(test_impl_.instrument_unsafe_references_);
579 E : EXPECT_FALSE(test_impl_.module_entry_only_);
580 E : }
581 :
582 E : TEST_F(InstrumentAppTest, InstrumentFailsInit) {
583 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
584 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
585 :
586 : EXPECT_CALL(test_impl_.mock_relinker_, Init())
587 E : .WillOnce(Return(false));
588 :
589 E : EXPECT_EQ(1, test_app_.Run());
590 E : }
591 :
592 E : TEST_F(InstrumentAppTest, InstrumentFailsRelink) {
593 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
594 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
595 :
596 : EXPECT_CALL(test_impl_.mock_relinker_, Init())
597 E : .WillOnce(Return(true));
598 :
599 : EXPECT_CALL(test_impl_.mock_relinker_, Relink())
600 E : .WillOnce(Return(false));
601 :
602 E : EXPECT_EQ(1, test_app_.Run());
603 E : }
604 :
605 E : TEST_F(InstrumentAppTest, Instrument) {
606 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
607 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
608 :
609 : EXPECT_CALL(test_impl_.mock_relinker_, Init())
610 E : .WillOnce(Return(true));
611 :
612 : EXPECT_CALL(test_impl_.mock_relinker_, Relink())
613 E : .WillOnce(Return(true));
614 :
615 E : ASSERT_EQ(0, test_app_.Run());
616 E : }
617 :
618 E : TEST_F(InstrumentAppTest, AsanEndToEnd) {
619 E : ASSERT_NO_FATAL_FAILURE(EndToEndTest("asan"));
620 E : }
621 :
622 E : TEST_F(InstrumentAppTest, BbEntryEndToEnd) {
623 E : ASSERT_NO_FATAL_FAILURE(EndToEndTest("bbentry"));
624 E : }
625 :
626 E : TEST_F(InstrumentAppTest, CallTraceEndToEnd) {
627 E : ASSERT_NO_FATAL_FAILURE(EndToEndTest("calltrace"));
628 E : }
629 :
630 E : TEST_F(InstrumentAppTest, CoverageEndToEnd) {
631 E : ASSERT_NO_FATAL_FAILURE(EndToEndTest("coverage"));
632 E : }
633 :
634 E : TEST_F(InstrumentAppTest, ProfileEndToEnd) {
635 E : ASSERT_NO_FATAL_FAILURE(EndToEndTest("profile"));
636 E : }
637 :
638 E : TEST_F(InstrumentAppTest, FailsWithInvalidFilter) {
639 : // Filters are applied in any mode, but run before any transformation is
640 : // actually done. Thus, we don't test this in combination with every mode.
641 E : cmd_line_.AppendSwitchASCII("mode", "asan");
642 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
643 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
644 E : cmd_line_.AppendSwitchPath("filter", dummy_filter_path_);
645 :
646 : // We don't expect the relinker to be called at all, as before we get that far
647 : // the filter will be identified as being for the wrong module.
648 :
649 E : MakeFilters();
650 E : ASSERT_NE(0, test_app_.Run());
651 E : }
652 :
653 E : TEST_F(InstrumentAppTest, SucceedsWithValidFilter) {
654 E : cmd_line_.AppendSwitchASCII("mode", "asan");
655 E : cmd_line_.AppendSwitchPath("input-image", input_dll_path_);
656 E : cmd_line_.AppendSwitchPath("output-image", output_dll_path_);
657 E : cmd_line_.AppendSwitchPath("filter", test_dll_filter_path_);
658 :
659 : EXPECT_CALL(test_impl_.mock_relinker_, Init())
660 E : .WillOnce(Return(true));
661 :
662 : EXPECT_CALL(test_impl_.mock_relinker_, Relink())
663 E : .WillOnce(Return(true));
664 :
665 E : MakeFilters();
666 E : ASSERT_EQ(0, test_app_.Run());
667 E : }
668 :
669 : } // namespace pe
|