1 : // Copyright 2013 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/pe/transforms/coff_prepare_headers_transform.h"
16 :
17 : #include "base/stringprintf.h"
18 : #include "gtest/gtest.h"
19 : #include "syzygy/block_graph/typed_block.h"
20 : #include "syzygy/block_graph/unittest_util.h"
21 : #include "syzygy/pe/pe_utils.h"
22 :
23 : namespace pe {
24 : namespace transforms {
25 :
26 : using block_graph::BlockGraph;
27 : using block_graph::ConstTypedBlock;
28 : using block_graph::TypedBlock;
29 :
30 : namespace {
31 :
32 : class CoffPrepareHeadersTransformTest : public testing::Test {
33 : public:
34 : CoffPrepareHeadersTransformTest()
35 : : expected_coff_headers_size_(0),
36 E : file_header_block_(NULL) {
37 E : }
38 :
39 E : virtual void SetUp() OVERRIDE {
40 E : block_graph_.AddSection(kCodeSectionName, kCodeCharacteristics);
41 : block_graph_.AddSection(kReadOnlyDataSectionName,
42 E : kReadOnlyDataCharacteristics);
43 : block_graph_.AddSection(kReadWriteDataSectionName,
44 E : kReadWriteDataCharacteristics);
45 E : block_graph_.AddSection(kTlsSectionName, kReadOnlyDataCharacteristics);
46 E : block_graph_.AddSection(kResourceSectionName, kReadOnlyDataCharacteristics);
47 E : block_graph_.AddSection(kRelocSectionName, kRelocCharacteristics);
48 :
49 : expected_coff_headers_size_ = sizeof(IMAGE_FILE_HEADER) +
50 E : block_graph_.sections().size() * sizeof(IMAGE_SECTION_HEADER);
51 E : }
52 :
53 : // Build a set of dummy COFF headers.
54 : //
55 : // @param num_sections the number of sections.
56 E : void BuildCoffHeaders(size_t num_sections) {
57 : size_t headers_size = sizeof(IMAGE_FILE_HEADER) +
58 E : num_sections * sizeof(IMAGE_SECTION_HEADER);
59 : file_header_block_ = block_graph_.AddBlock(BlockGraph::DATA_BLOCK,
60 E : headers_size, "COFF Headers");
61 E : ASSERT_TRUE(file_header_block_ != NULL);
62 E : file_header_block_->AllocateData(file_header_block_->size());
63 :
64 : // Add dummy reference that should be removed by the transform.
65 : BlockGraph::Reference ref(BlockGraph::RELATIVE_REF, 4,
66 E : file_header_block_, 0, 0);
67 E : file_header_block_->SetReference(10, ref);
68 E : }
69 :
70 : size_t expected_coff_headers_size_;
71 :
72 : testing::DummyTransformPolicy policy_;
73 : BlockGraph block_graph_;
74 : BlockGraph::Block* file_header_block_;
75 : };
76 :
77 : } // namespace
78 :
79 E : TEST_F(CoffPrepareHeadersTransformTest, ShrinkCoffHeaders) {
80 E : BuildCoffHeaders(block_graph_.sections().size() + 2);
81 E : ASSERT_TRUE(file_header_block_ != NULL);
82 :
83 E : CoffPrepareHeadersTransform tx;
84 : EXPECT_TRUE(tx.TransformBlockGraph(
85 E : &policy_, &block_graph_, file_header_block_));
86 :
87 E : ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
88 E : ASSERT_TRUE(file_header.Init(0, file_header_block_));
89 :
90 E : EXPECT_FALSE(IsValidDosHeaderBlock(file_header_block_));
91 E : EXPECT_EQ(expected_coff_headers_size_, file_header_block_->size());
92 E : EXPECT_EQ(block_graph_.sections().size(), file_header->NumberOfSections);
93 E : }
94 :
95 E : TEST_F(CoffPrepareHeadersTransformTest, GrowCoffHeaders) {
96 E : size_t num_sections = block_graph_.sections().size() - 2;
97 E : ASSERT_LT(num_sections, block_graph_.sections().size());
98 E : BuildCoffHeaders(num_sections);
99 E : ASSERT_TRUE(file_header_block_ != NULL);
100 :
101 E : CoffPrepareHeadersTransform tx;
102 : EXPECT_TRUE(tx.TransformBlockGraph(
103 E : &policy_, &block_graph_, file_header_block_));
104 :
105 E : ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
106 E : ASSERT_TRUE(file_header.Init(0, file_header_block_));
107 :
108 E : EXPECT_FALSE(IsValidDosHeaderBlock(file_header_block_));
109 E : EXPECT_EQ(0, file_header_block_->references().size());
110 E : EXPECT_EQ(expected_coff_headers_size_, file_header_block_->size());
111 E : EXPECT_EQ(block_graph_.sections().size(), file_header->NumberOfSections);
112 E : }
113 :
114 : } // namespace transforms
115 : } // namespace pe
|