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/strings/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_.set_image_format(BlockGraph::COFF_IMAGE);
41 E : block_graph_.AddSection(kCodeSectionName, kCodeCharacteristics);
42 : block_graph_.AddSection(kReadOnlyDataSectionName,
43 E : kReadOnlyDataCharacteristics);
44 : block_graph_.AddSection(kReadWriteDataSectionName,
45 E : kReadWriteDataCharacteristics);
46 E : block_graph_.AddSection(kTlsSectionName, kReadOnlyDataCharacteristics);
47 E : block_graph_.AddSection(kResourceSectionName, kReadOnlyDataCharacteristics);
48 E : block_graph_.AddSection(kRelocSectionName, kRelocCharacteristics);
49 :
50 : expected_coff_headers_size_ = sizeof(IMAGE_FILE_HEADER) +
51 E : block_graph_.sections().size() * sizeof(IMAGE_SECTION_HEADER);
52 E : }
53 :
54 : // Build a set of dummy COFF headers.
55 : //
56 : // @param num_sections the number of sections.
57 E : void BuildCoffHeaders(size_t num_sections) {
58 : size_t headers_size = sizeof(IMAGE_FILE_HEADER) +
59 E : num_sections * sizeof(IMAGE_SECTION_HEADER);
60 : file_header_block_ = block_graph_.AddBlock(BlockGraph::DATA_BLOCK,
61 E : headers_size, "COFF Headers");
62 E : ASSERT_TRUE(file_header_block_ != NULL);
63 E : file_header_block_->AllocateData(file_header_block_->size());
64 :
65 : // Add dummy reference that should be removed by the transform.
66 : BlockGraph::Reference ref(BlockGraph::RELATIVE_REF, 4,
67 E : file_header_block_, 0, 0);
68 E : file_header_block_->SetReference(10, ref);
69 E : }
70 :
71 : size_t expected_coff_headers_size_;
72 :
73 : testing::DummyTransformPolicy policy_;
74 : BlockGraph block_graph_;
75 : BlockGraph::Block* file_header_block_;
76 : };
77 :
78 : } // namespace
79 :
80 E : TEST_F(CoffPrepareHeadersTransformTest, ShrinkCoffHeaders) {
81 E : BuildCoffHeaders(block_graph_.sections().size() + 2);
82 E : ASSERT_TRUE(file_header_block_ != NULL);
83 :
84 E : CoffPrepareHeadersTransform tx;
85 : EXPECT_TRUE(tx.TransformBlockGraph(
86 E : &policy_, &block_graph_, file_header_block_));
87 :
88 E : ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
89 E : ASSERT_TRUE(file_header.Init(0, file_header_block_));
90 :
91 E : EXPECT_FALSE(IsValidDosHeaderBlock(file_header_block_));
92 E : EXPECT_EQ(expected_coff_headers_size_, file_header_block_->size());
93 E : EXPECT_EQ(block_graph_.sections().size(), file_header->NumberOfSections);
94 E : }
95 :
96 E : TEST_F(CoffPrepareHeadersTransformTest, GrowCoffHeaders) {
97 E : size_t num_sections = block_graph_.sections().size() - 2;
98 E : ASSERT_LT(num_sections, block_graph_.sections().size());
99 E : BuildCoffHeaders(num_sections);
100 E : ASSERT_TRUE(file_header_block_ != NULL);
101 :
102 E : CoffPrepareHeadersTransform tx;
103 : EXPECT_TRUE(tx.TransformBlockGraph(
104 E : &policy_, &block_graph_, file_header_block_));
105 :
106 E : ConstTypedBlock<IMAGE_FILE_HEADER> file_header;
107 E : ASSERT_TRUE(file_header.Init(0, file_header_block_));
108 :
109 E : EXPECT_FALSE(IsValidDosHeaderBlock(file_header_block_));
110 E : EXPECT_EQ(0, file_header_block_->references().size());
111 E : EXPECT_EQ(expected_coff_headers_size_, file_header_block_->size());
112 E : EXPECT_EQ(block_graph_.sections().size(), file_header->NumberOfSections);
113 E : }
114 :
115 : } // namespace transforms
116 : } // namespace pe
|