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/relink/relink_app.h"
16 :
17 : #include "base/stringprintf.h"
18 : #include "gmock/gmock.h"
19 : #include "gtest/gtest.h"
20 : #include "syzygy/block_graph/basic_block_decomposer.h"
21 : #include "syzygy/block_graph/typed_block.h"
22 : #include "syzygy/block_graph/unittest_util.h"
23 : #include "syzygy/common/unittest_util.h"
24 : #include "syzygy/core/unittest_util.h"
25 : #include "syzygy/pe/decomposer.h"
26 : #include "syzygy/pe/pe_utils.h"
27 : #include "syzygy/pe/unittest_util.h"
28 : #include "syzygy/reorder/reorderer.h"
29 :
30 : namespace relink {
31 :
32 : using block_graph::BlockGraph;
33 : using common::Application;
34 : using core::RelativeAddress;
35 : using ::testing::ScopedLogLevelSaver;
36 :
37 : namespace {
38 :
39 : class TestRelinkApp : public RelinkApp {
40 : public:
41 : using RelinkApp::input_image_path_;
42 : using RelinkApp::input_pdb_path_;
43 : using RelinkApp::output_image_path_;
44 : using RelinkApp::output_pdb_path_;
45 : using RelinkApp::order_file_path_;
46 : using RelinkApp::seed_;
47 : using RelinkApp::padding_;
48 : using RelinkApp::no_augment_pdb_;
49 : using RelinkApp::compress_pdb_;
50 : using RelinkApp::no_strip_strings_;
51 : using RelinkApp::output_metadata_;
52 : using RelinkApp::overwrite_;
53 : using RelinkApp::fuzz_;
54 : };
55 :
56 : typedef common::Application<TestRelinkApp> TestApp;
57 :
58 : class RelinkAppTest : public testing::PELibUnitTest {
59 : public:
60 : typedef testing::PELibUnitTest Super;
61 :
62 : RelinkAppTest()
63 : : cmd_line_(base::FilePath(L"relink.exe")),
64 : test_impl_(test_app_.implementation()),
65 : seed_(1234567),
66 : padding_(32),
67 : no_augment_pdb_(false),
68 : compress_pdb_(false),
69 : no_strip_strings_(false),
70 : output_metadata_(false),
71 E : overwrite_(false) {
72 E : }
73 :
74 E : void SetUp() {
75 E : Super::SetUp();
76 :
77 : // Several of the tests generate progress and (deliberate) error messages
78 : // that would otherwise clutter the unittest output.
79 E : logging::SetMinLogLevel(logging::LOG_FATAL);
80 :
81 : // Setup the IO streams.
82 E : CreateTemporaryDir(&temp_dir_);
83 E : stdin_path_ = temp_dir_.Append(L"NUL");
84 E : stdout_path_ = temp_dir_.Append(L"stdout.txt");
85 E : stderr_path_ = temp_dir_.Append(L"stderr.txt");
86 E : InitStreams(stdin_path_, stdout_path_, stderr_path_);
87 :
88 : // Initialize the (potential) input and output path values.
89 E : abs_input_image_path_ = testing::GetExeRelativePath(testing::kTestDllName);
90 E : input_image_path_ = testing::GetRelativePath(abs_input_image_path_);
91 E : abs_input_pdb_path_ = testing::GetExeRelativePath(testing::kTestDllPdbName);
92 E : input_pdb_path_ = testing::GetRelativePath(abs_input_pdb_path_);
93 E : output_image_path_ = temp_dir_.Append(input_image_path_.BaseName());
94 E : output_pdb_path_ = temp_dir_.Append(input_pdb_path_.BaseName());
95 E : order_file_path_ = temp_dir_.Append(L"order.json");
96 :
97 : // Point the application at the test's command-line and IO streams.
98 E : test_app_.set_command_line(&cmd_line_);
99 E : test_app_.set_in(in());
100 E : test_app_.set_out(out());
101 E : test_app_.set_err(err());
102 E : }
103 :
104 E : void GetDllMain(const pe::ImageLayout& layout, BlockGraph::Block** dll_main) {
105 E : ASSERT_TRUE(dll_main != NULL);
106 : BlockGraph::Block* dos_header_block = layout.blocks.GetBlockByAddress(
107 E : RelativeAddress(0));
108 E : ASSERT_TRUE(dos_header_block != NULL);
109 : BlockGraph::Block* nt_headers_block =
110 E : pe::GetNtHeadersBlockFromDosHeaderBlock(dos_header_block);
111 E : ASSERT_TRUE(nt_headers_block != NULL);
112 E : block_graph::ConstTypedBlock<IMAGE_NT_HEADERS> nt_headers;
113 E : ASSERT_TRUE(nt_headers.Init(0, nt_headers_block));
114 E : BlockGraph::Reference dll_main_ref;
115 E : ASSERT_TRUE(nt_headers_block->GetReference(
116 : nt_headers.OffsetOf(nt_headers->OptionalHeader.AddressOfEntryPoint),
117 : &dll_main_ref));
118 E : ASSERT_EQ(0u, dll_main_ref.offset());
119 E : ASSERT_EQ(0u, dll_main_ref.base());
120 E : *dll_main = dll_main_ref.referenced();
121 E : }
122 :
123 : // Stashes the current log-level before each test instance and restores it
124 : // after each test completes.
125 : ScopedLogLevelSaver log_level_saver;
126 :
127 : // @name The application under test.
128 : // @{
129 : TestApp test_app_;
130 : TestApp::Implementation& test_impl_;
131 : base::FilePath temp_dir_;
132 : base::FilePath stdin_path_;
133 : base::FilePath stdout_path_;
134 : base::FilePath stderr_path_;
135 : // @}
136 :
137 : // @name Command-line and parameters.
138 : // @{
139 : CommandLine cmd_line_;
140 : base::FilePath input_image_path_;
141 : base::FilePath input_pdb_path_;
142 : base::FilePath output_image_path_;
143 : base::FilePath output_pdb_path_;
144 : base::FilePath order_file_path_;
145 : uint32 seed_;
146 : size_t padding_;
147 : bool no_augment_pdb_;
148 : bool compress_pdb_;
149 : bool no_strip_strings_;
150 : bool output_metadata_;
151 : bool overwrite_;
152 : // @}
153 :
154 : // @name Expected final values of input parameters.
155 : // @{
156 : base::FilePath abs_input_image_path_;
157 : base::FilePath abs_input_pdb_path_;
158 : // @}
159 : };
160 :
161 : } // namespace
162 :
163 E : TEST_F(RelinkAppTest, GetHelp) {
164 E : cmd_line_.AppendSwitch("help");
165 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
166 E : }
167 :
168 E : TEST_F(RelinkAppTest, EmptyCommandLineFails) {
169 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
170 E : }
171 :
172 E : TEST_F(RelinkAppTest, ParseWithNeitherInputNorOrderFails) {
173 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
174 :
175 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
176 E : }
177 :
178 E : TEST_F(RelinkAppTest, ParseWithSeedAndOrderFails) {
179 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
180 E : cmd_line_.AppendSwitchASCII("seed", base::StringPrintf("%d", seed_));
181 E : cmd_line_.AppendSwitchPath("order_file", order_file_path_);
182 :
183 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
184 E : }
185 :
186 E : TEST_F(RelinkAppTest, ParseWithEmptySeedFails) {
187 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
188 E : cmd_line_.AppendSwitch("seed");
189 :
190 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
191 E : }
192 :
193 E : TEST_F(RelinkAppTest, ParseWithInvalidSeedFails) {
194 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
195 E : cmd_line_.AppendSwitchASCII("seed", "hello");
196 :
197 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
198 E : }
199 :
200 E : TEST_F(RelinkAppTest, ParseWithEmptyPaddingFails) {
201 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
202 E : cmd_line_.AppendSwitch("padding");
203 :
204 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
205 E : }
206 :
207 E : TEST_F(RelinkAppTest, ParseWithInvalidPaddingFails) {
208 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
209 E : cmd_line_.AppendSwitchASCII("padding", "hello");
210 :
211 E : ASSERT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
212 E : }
213 :
214 E : TEST_F(RelinkAppTest, ParseMinimalCommandLineWithInputDll) {
215 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
216 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
217 :
218 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
219 E : EXPECT_TRUE(test_impl_.SetUp());
220 E : }
221 :
222 E : TEST_F(RelinkAppTest, ParseMinimalCommandLineWithOrderFile) {
223 : // The order file doesn't actually exist, so setup should fail to infer the
224 : // input dll.
225 E : cmd_line_.AppendSwitchPath("order-file", order_file_path_);
226 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
227 :
228 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
229 :
230 E : EXPECT_EQ(0, test_impl_.seed_);
231 E : EXPECT_EQ(0, test_impl_.padding_);
232 E : EXPECT_FALSE(test_impl_.no_augment_pdb_);
233 E : EXPECT_FALSE(test_impl_.compress_pdb_);
234 E : EXPECT_FALSE(test_impl_.no_strip_strings_);
235 E : EXPECT_TRUE(test_impl_.output_metadata_);
236 E : EXPECT_FALSE(test_impl_.overwrite_);
237 E : EXPECT_FALSE(test_impl_.fuzz_);
238 :
239 E : EXPECT_FALSE(test_impl_.SetUp());
240 E : }
241 :
242 E : TEST_F(RelinkAppTest, ParseFullCommandLineWithOrderFile) {
243 : // Note that we specify the no-metadata flag, so we expect false below
244 : // for the output_metadata_ member. Also note that neither seed nor padding
245 : // are given, and should default to 0.
246 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
247 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
248 E : cmd_line_.AppendSwitchPath("order-file", order_file_path_);
249 E : cmd_line_.AppendSwitch("no-augment-pdb");
250 E : cmd_line_.AppendSwitch("compress-pdb");
251 E : cmd_line_.AppendSwitch("no-strip-strings");
252 E : cmd_line_.AppendSwitch("no-metadata");
253 E : cmd_line_.AppendSwitch("overwrite");
254 E : cmd_line_.AppendSwitch("fuzz");
255 :
256 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
257 E : EXPECT_TRUE(test_impl_.input_image_path_.empty());
258 E : EXPECT_TRUE(test_impl_.input_pdb_path_.empty());
259 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
260 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
261 E : EXPECT_EQ(order_file_path_, test_impl_.order_file_path_);
262 E : EXPECT_EQ(0, test_impl_.seed_);
263 E : EXPECT_EQ(0, test_impl_.padding_);
264 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
265 E : EXPECT_TRUE(test_impl_.compress_pdb_);
266 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
267 E : EXPECT_FALSE(test_impl_.output_metadata_);
268 E : EXPECT_TRUE(test_impl_.overwrite_);
269 E : EXPECT_TRUE(test_impl_.fuzz_);
270 :
271 : // The order file doesn't actually exist, so setup should fail to infer the
272 : // input dll.
273 E : EXPECT_FALSE(test_impl_.SetUp());
274 E : }
275 :
276 E : TEST_F(RelinkAppTest, ParseFullCommandLineWithInputSeedAndMetadata) {
277 : // Note that we omit the no-metadata flag, so we expect true below for the
278 : // output_metadata_ member.
279 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
280 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
281 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
282 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
283 E : cmd_line_.AppendSwitchASCII("seed", base::StringPrintf("%d", seed_));
284 E : cmd_line_.AppendSwitchASCII("padding", base::StringPrintf("%d", padding_));
285 E : cmd_line_.AppendSwitch("no-augment-pdb");
286 E : cmd_line_.AppendSwitch("compress-pdb");
287 E : cmd_line_.AppendSwitch("no-strip-strings");
288 E : cmd_line_.AppendSwitch("overwrite");
289 E : cmd_line_.AppendSwitch("fuzz");
290 :
291 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
292 E : EXPECT_EQ(abs_input_image_path_, test_impl_.input_image_path_);
293 E : EXPECT_EQ(abs_input_pdb_path_, test_impl_.input_pdb_path_);
294 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
295 E : EXPECT_EQ(output_pdb_path_, test_impl_.output_pdb_path_);
296 E : EXPECT_TRUE(test_impl_.order_file_path_.empty());
297 E : EXPECT_EQ(seed_, test_impl_.seed_);
298 E : EXPECT_EQ(padding_, test_impl_.padding_);
299 E : EXPECT_TRUE(test_impl_.no_augment_pdb_);
300 E : EXPECT_TRUE(test_impl_.compress_pdb_);
301 E : EXPECT_TRUE(test_impl_.no_strip_strings_);
302 E : EXPECT_TRUE(test_impl_.output_metadata_);
303 E : EXPECT_TRUE(test_impl_.overwrite_);
304 E : EXPECT_TRUE(test_impl_.fuzz_);
305 :
306 : // SetUp() has nothing else to infer so it should succeed.
307 E : EXPECT_TRUE(test_impl_.SetUp());
308 E : }
309 :
310 E : TEST_F(RelinkAppTest, DeprecatedFlagsSucceeds) {
311 E : cmd_line_.AppendSwitchPath("input-dll", input_image_path_);
312 E : cmd_line_.AppendSwitchPath("output-dll", output_image_path_);
313 E : EXPECT_TRUE(test_impl_.ParseCommandLine(&cmd_line_));
314 :
315 E : EXPECT_EQ(abs_input_image_path_, test_impl_.input_image_path_);
316 E : EXPECT_EQ(output_image_path_, test_impl_.output_image_path_);
317 E : }
318 :
319 E : TEST_F(RelinkAppTest, DeprecatedFlagsConflictingInputsFail) {
320 E : cmd_line_.AppendSwitchPath("input-dll", input_image_path_);
321 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
322 E : cmd_line_.AppendSwitchPath("output-dll", output_image_path_);
323 E : EXPECT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
324 E : }
325 :
326 E : TEST_F(RelinkAppTest, DeprecatedFlagsConflictingOutputsFail) {
327 E : cmd_line_.AppendSwitchPath("input-dll", input_image_path_);
328 E : cmd_line_.AppendSwitchPath("output-dll", output_image_path_);
329 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
330 E : EXPECT_FALSE(test_impl_.ParseCommandLine(&cmd_line_));
331 E : }
332 :
333 E : TEST_F(RelinkAppTest, RandomRelink) {
334 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
335 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
336 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
337 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
338 E : cmd_line_.AppendSwitchASCII("seed", base::StringPrintf("%d", seed_));
339 E : cmd_line_.AppendSwitchASCII("padding", base::StringPrintf("%d", padding_));
340 E : cmd_line_.AppendSwitch("overwrite");
341 :
342 E : ASSERT_EQ(0, test_app_.Run());
343 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
344 E : }
345 :
346 E : TEST_F(RelinkAppTest, RandomRelinkBasicBlocks) {
347 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
348 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
349 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
350 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
351 E : cmd_line_.AppendSwitchASCII("seed", base::StringPrintf("%d", seed_));
352 E : cmd_line_.AppendSwitchASCII("padding", base::StringPrintf("%d", padding_));
353 E : cmd_line_.AppendSwitch("overwrite");
354 E : cmd_line_.AppendSwitch("basic-blocks");
355 E : cmd_line_.AppendSwitch("exclude-bb-padding");
356 :
357 E : ASSERT_EQ(0, test_app_.Run());
358 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
359 E : }
360 :
361 E : TEST_F(RelinkAppTest, RandomRelinkBasicBlocksWithFuzzing) {
362 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
363 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
364 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
365 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
366 E : cmd_line_.AppendSwitchASCII("seed", base::StringPrintf("%d", seed_));
367 E : cmd_line_.AppendSwitchASCII("padding", base::StringPrintf("%d", padding_));
368 E : cmd_line_.AppendSwitch("overwrite");
369 E : cmd_line_.AppendSwitch("basic-blocks");
370 E : cmd_line_.AppendSwitch("exclude-bb-padding");
371 E : cmd_line_.AppendSwitch("fuzz");
372 :
373 E : ASSERT_EQ(0, test_app_.Run());
374 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
375 E : }
376 :
377 E : TEST_F(RelinkAppTest, RelinkBlockOrder) {
378 E : pe::PEFile pe_file;
379 E : ASSERT_TRUE(pe_file.Init(input_image_path_));
380 :
381 E : BlockGraph bg;
382 E : pe::ImageLayout layout(&bg);
383 E : pe::Decomposer decomposer(pe_file);
384 E : ASSERT_TRUE(decomposer.Decompose(&layout));
385 :
386 : // Get the DLL main entry point.
387 E : BlockGraph::Block* dll_main_block = NULL;
388 E : ASSERT_NO_FATAL_FAILURE(GetDllMain(layout, &dll_main_block));
389 :
390 : // Build a block-level ordering by placing the DLL main entry point at the
391 : // beginning of its section.
392 E : BlockGraph::Section* text_section = bg.FindSection(".text");
393 E : ASSERT_TRUE(text_section != NULL);
394 E : reorder::Reorderer::Order order;
395 E : order.sections.resize(1);
396 E : order.sections[0].id = text_section->id();
397 E : order.sections[0].name = text_section->name();
398 E : order.sections[0].characteristics = text_section->characteristics();
399 E : order.sections[0].blocks.resize(1);
400 E : order.sections[0].blocks[0].block = dll_main_block;
401 :
402 : // Serialize the order file.
403 E : ASSERT_TRUE(order.SerializeToJSON(pe_file, order_file_path_, false));
404 :
405 : // Order the test DLL using the order file we just created.
406 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
407 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
408 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
409 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
410 E : cmd_line_.AppendSwitchPath("order-file", order_file_path_);
411 E : ASSERT_EQ(0, test_app_.Run());
412 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
413 E : }
414 :
415 E : TEST_F(RelinkAppTest, RelinkTestDataBlockOrder) {
416 : // Try a block-level reordering using an actual order file generated by our
417 : // test_data dependency.
418 :
419 : base::FilePath test_dll_order_json =
420 E : testing::GetExeTestDataRelativePath(L"test_dll_order.json");
421 :
422 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
423 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
424 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
425 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
426 E : cmd_line_.AppendSwitchPath("order-file", test_dll_order_json);
427 E : ASSERT_EQ(0, test_app_.Run());
428 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
429 E : }
430 :
431 E : TEST_F(RelinkAppTest, RelinkBasicBlockOrder) {
432 E : pe::PEFile pe_file;
433 E : ASSERT_TRUE(pe_file.Init(input_image_path_));
434 :
435 E : BlockGraph bg;
436 E : pe::ImageLayout layout(&bg);
437 E : pe::Decomposer decomposer(pe_file);
438 E : ASSERT_TRUE(decomposer.Decompose(&layout));
439 :
440 : // Get the DLL main entry point.
441 E : BlockGraph::Block* dll_main_block = NULL;
442 E : ASSERT_NO_FATAL_FAILURE(GetDllMain(layout, &dll_main_block));
443 :
444 : // Build a block-level ordering by splitting the DLL main block into two
445 : // blocks, each half in a different section.
446 E : BlockGraph::Section* text_section = bg.FindSection(".text");
447 E : ASSERT_TRUE(text_section != NULL);
448 E : reorder::Reorderer::Order order;
449 E : order.sections.resize(2);
450 E : order.sections[0].id = text_section->id();
451 E : order.sections[0].name = text_section->name();
452 E : order.sections[0].characteristics = text_section->characteristics();
453 E : order.sections[0].blocks.resize(1);
454 E : order.sections[0].blocks[0].block = dll_main_block;
455 E : order.sections[1].id = reorder::Reorderer::Order::SectionSpec::kNewSectionId;
456 E : order.sections[1].name = ".text2";
457 E : order.sections[1].characteristics = text_section->characteristics();
458 E : order.sections[1].blocks.resize(1);
459 E : order.sections[1].blocks[0].block = dll_main_block;
460 :
461 : // Decompose the block. Iterate over its basic-blocks and take turns placing
462 : // them into each of the two above blocks.
463 E : block_graph::BasicBlockSubGraph bbsg;
464 E : block_graph::BasicBlockDecomposer bb_decomposer(dll_main_block, &bbsg);
465 E : ASSERT_TRUE(bb_decomposer.Decompose());
466 E : ASSERT_LE(2u, bbsg.basic_blocks().size());
467 : block_graph::BasicBlockSubGraph::BBCollection::const_iterator bb_it =
468 E : bbsg.basic_blocks().begin();
469 E : for (size_t i = 0; bb_it != bbsg.basic_blocks().end(); ++bb_it, i ^= 1) {
470 : order.sections[i].blocks[0].basic_block_offsets.push_back(
471 E : (*bb_it)->offset());
472 E : }
473 :
474 : // Serialize the order file.
475 E : ASSERT_TRUE(order.SerializeToJSON(pe_file, order_file_path_, false));
476 :
477 : // Order the test DLL using the order file we just created.
478 E : cmd_line_.AppendSwitchPath("input-image", input_image_path_);
479 E : cmd_line_.AppendSwitchPath("input-pdb", input_pdb_path_);
480 E : cmd_line_.AppendSwitchPath("output-image", output_image_path_);
481 E : cmd_line_.AppendSwitchPath("output-pdb", output_pdb_path_);
482 E : cmd_line_.AppendSwitchPath("order-file", order_file_path_);
483 E : ASSERT_EQ(0, test_app_.Run());
484 E : ASSERT_NO_FATAL_FAILURE(CheckTestDll(output_image_path_));
485 E : }
486 :
487 : } // namespace relink
|