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