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