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