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/pe/transforms/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/pe/pe_utils.h"
21 :
22 : namespace pe {
23 : namespace transforms {
24 :
25 : using block_graph::BlockGraph;
26 : using block_graph::ConstTypedBlock;
27 : using block_graph::TypedBlock;
28 :
29 : namespace {
30 :
31 : class PrepareHeadersTransformTest : public testing::Test {
32 : public:
33 E : PrepareHeadersTransformTest()
34 : : dos_header_block_(NULL), nt_headers_block_(NULL) {
35 E : }
36 :
37 E : virtual void SetUp() {
38 E : block_graph_.AddSection(kCodeSectionName, kCodeCharacteristics);
39 : block_graph_.AddSection(kReadOnlyDataSectionName,
40 E : kReadOnlyDataCharacteristics);
41 : block_graph_.AddSection(kReadWriteDataSectionName,
42 E : kReadWriteDataCharacteristics);
43 E : block_graph_.AddSection(kTlsSectionName, kReadOnlyDataCharacteristics);
44 : block_graph_.AddSection(kResourceSectionName,
45 E : kReadOnlyDataCharacteristics);
46 E : block_graph_.AddSection(kRelocSectionName, kRelocCharacteristics);
47 :
48 E : expected_dos_header_size_ = sizeof(IMAGE_DOS_HEADER);
49 : expected_nt_headers_size_ = sizeof(IMAGE_NT_HEADERS) +
50 E : block_graph_.sections().size() * sizeof(IMAGE_SECTION_HEADER);
51 E : }
52 :
53 : // Builds a set of dummy DOS and NT headers.
54 E : void BuildHeaders(size_t extra_dos_header_bytes, size_t section_count) {
55 : dos_header_block_ = block_graph_.AddBlock(BlockGraph::DATA_BLOCK,
56 : sizeof(IMAGE_DOS_HEADER) + extra_dos_header_bytes,
57 E : "Dos Header");
58 E : ASSERT_TRUE(dos_header_block_ != NULL);
59 E : dos_header_block_->AllocateData(dos_header_block_->size());
60 :
61 : nt_headers_block_ = block_graph_.AddBlock(BlockGraph::DATA_BLOCK,
62 : sizeof(IMAGE_NT_HEADERS) + section_count * sizeof(IMAGE_SECTION_HEADER),
63 E : "Nt Headers");
64 E : ASSERT_TRUE(nt_headers_block_ != NULL);
65 E : nt_headers_block_->AllocateData(nt_headers_block_->size());
66 :
67 E : TypedBlock<IMAGE_DOS_HEADER> dos_header;
68 E : ASSERT_TRUE(dos_header.Init(0, dos_header_block_));
69 : dos_header.SetReference(BlockGraph::RELATIVE_REF,
70 : dos_header->e_lfanew,
71 : nt_headers_block_,
72 E : 0, 0);
73 :
74 E : TypedBlock<IMAGE_NT_HEADERS> nt_headers;
75 E : ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
76 E : nt_headers->OptionalHeader.FileAlignment = 512;
77 E : }
78 :
79 : size_t expected_dos_header_size_;
80 : size_t expected_nt_headers_size_;
81 :
82 : BlockGraph block_graph_;
83 : BlockGraph::Block* dos_header_block_;
84 : BlockGraph::Block* nt_headers_block_;
85 : };
86 :
87 : } // namespace
88 :
89 E : TEST_F(PrepareHeadersTransformTest, ShrinkHeaders) {
90 E : BuildHeaders(100, block_graph_.sections().size() + 2);
91 :
92 E : PrepareHeadersTransform tx;
93 E : EXPECT_TRUE(tx.TransformBlockGraph(&block_graph_, dos_header_block_));
94 :
95 E : ConstTypedBlock<IMAGE_NT_HEADERS> nt_headers;
96 E : ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
97 :
98 E : EXPECT_TRUE(IsValidDosHeaderBlock(dos_header_block_));
99 E : EXPECT_EQ(expected_nt_headers_size_, nt_headers_block_->size());
100 E : EXPECT_EQ(expected_nt_headers_size_, nt_headers_block_->data_size());
101 : EXPECT_EQ(block_graph_.sections().size(),
102 E : nt_headers->FileHeader.NumberOfSections);
103 E : }
104 :
105 E : TEST_F(PrepareHeadersTransformTest, GrowHeaders) {
106 E : size_t section_count = block_graph_.sections().size() - 2;
107 E : ASSERT_LT(section_count, block_graph_.sections().size());
108 E : BuildHeaders(0, section_count);
109 :
110 E : PrepareHeadersTransform tx;
111 E : EXPECT_TRUE(tx.TransformBlockGraph(&block_graph_, dos_header_block_));
112 :
113 E : ConstTypedBlock<IMAGE_NT_HEADERS> nt_headers;
114 E : ASSERT_TRUE(nt_headers.Init(0, nt_headers_block_));
115 :
116 E : EXPECT_TRUE(IsValidDosHeaderBlock(dos_header_block_));
117 E : EXPECT_EQ(expected_nt_headers_size_, nt_headers_block_->size());
118 E : EXPECT_EQ(expected_nt_headers_size_, nt_headers_block_->data_size());
119 : EXPECT_EQ(block_graph_.sections().size(),
120 E : nt_headers->FileHeader.NumberOfSections);
121 E : }
122 :
123 : } // namespace transforms
124 : } // namespace pe
|