1 : // Copyright 2011 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 : // Contains unittests for ImageSourceMap.
16 :
17 : #include "syzygy/pe/image_source_map.h"
18 :
19 : #include "gmock/gmock.h"
20 : #include "syzygy/core/unittest_util.h"
21 : #include "syzygy/pdb/omap.h"
22 : #include "syzygy/pe/decomposer.h"
23 : #include "syzygy/pe/unittest_util.h"
24 :
25 : // A comparison operator for OMAP objects so that we can use ContainerEq.
26 E : bool operator==(const OMAP& omap1, const OMAP& omap2) {
27 : return omap1.rva == omap2.rva &&
28 E : omap1.rvaTo == omap2.rvaTo;
29 E : }
30 :
31 : namespace pe {
32 :
33 : using block_graph::BlockGraph;
34 : using core::RelativeAddress;
35 :
36 : namespace {
37 :
38 : class ImageSourceMapTest: public testing::PELibUnitTest {
39 : // Insert your customizations here.
40 : };
41 :
42 : // Acts as a constructor for OMAP objects.
43 E : OMAP BuildOmap(ULONG rva, ULONG rvaTo) {
44 E : OMAP omap = { rva, rvaTo };
45 E : return omap;
46 E : }
47 :
48 : // Returns true if the given OMAP vector is valid. That is, if it is sorted
49 : // according to rva values.
50 E : bool IsValidOmapVector(const std::vector<OMAP>& omap) {
51 E : for (size_t i = 1; i < omap.size(); ++i) {
52 E : if (omap[i].rva <= omap[i - 1].rva)
53 i : return false;
54 E : }
55 E : return true;
56 E : }
57 :
58 : } // namespace
59 :
60 E : TEST_F(ImageSourceMapTest, FromUntransformedImageLayout) {
61 E : base::FilePath image_path(testing::GetExeRelativePath(testing::kTestDllName));
62 E : PEFile image_file;
63 :
64 E : ASSERT_TRUE(image_file.Init(image_path));
65 :
66 E : Decomposer decomposer(image_file);
67 E : BlockGraph block_graph;
68 E : ImageLayout image_layout(&block_graph);
69 E : ASSERT_TRUE(decomposer.Decompose(&image_layout));
70 :
71 E : ImageSourceMap source_map;
72 E : BuildImageSourceMap(image_layout, &source_map);
73 E : EXPECT_GT(source_map.size(), 0u);
74 :
75 : // We expect every entry of the resulting map to be an identity mapping.
76 : ImageSourceMap::RangePairs::const_iterator it =
77 E : source_map.range_pairs().begin();
78 E : for (; it != source_map.range_pairs().end(); ++it)
79 E : EXPECT_EQ(it->first, it->second);
80 E : }
81 :
82 E : TEST_F(ImageSourceMapTest, OmapConversion) {
83 : // We imagine an original image with the following layout:
84 : //
85 : // 512 128 128
86 : // +---------+-------+-----+-------+-----+-------+
87 : // | HEADERS | empty | A | empty | B | empty |
88 : // +---------+-------+-----+-------+-----+-------+
89 : // 0 512 1024 1152 1536 1664 2048
90 : //
91 : // and consider it post-transform with this layout:
92 : //
93 : // 512 128 128
94 : // +---------+-------+-----+-----+-------+
95 : // | HEADERS | empty | B | A | empty |
96 : // +---------+-------+-----+-----+-------+
97 : // 0 512 1024 1152 1280 1536
98 :
99 E : const RelativeAddressRange h_old(RelativeAddress(0), 512);
100 E : const RelativeAddressRange h_new(RelativeAddress(0), 512);
101 E : const RelativeAddressRange a_old(RelativeAddress(1024), 128);
102 E : const RelativeAddressRange a_new(RelativeAddress(1152), 128);
103 E : const RelativeAddressRange b_old(RelativeAddress(1536), 128);
104 E : const RelativeAddressRange b_new(RelativeAddress(1024), 128);
105 E : const size_t size_new = 1536;
106 :
107 E : ImageSourceMap source_map;
108 E : ASSERT_TRUE(source_map.Push(h_new, h_old));
109 E : ASSERT_TRUE(source_map.Push(b_new, b_old));
110 E : ASSERT_TRUE(source_map.Push(a_new, a_old));
111 :
112 E : std::vector<OMAP> omap_to;
113 : BuildOmapVectorFromImageSourceMap(
114 E : RelativeAddressRange(RelativeAddress(0), size_new), source_map, &omap_to);
115 E : EXPECT_TRUE(IsValidOmapVector(omap_to));
116 :
117 E : std::vector<OMAP> expected;
118 E : expected.push_back(BuildOmap(0, 0));
119 E : expected.push_back(BuildOmap(512, kInvalidOmapRvaTo));
120 E : expected.push_back(BuildOmap(1024, 1536));
121 E : expected.push_back(BuildOmap(1152, 1024));
122 E : expected.push_back(BuildOmap(1280, kInvalidOmapRvaTo));
123 E : expected.push_back(BuildOmap(1536, kInvalidOmapRvaTo));
124 E : EXPECT_THAT(expected, testing::ContainerEq(omap_to));
125 E : }
126 :
127 E : TEST_F(ImageSourceMapTest, OmapShrinkingRanges) {
128 E : ImageSourceMap source_map;
129 E : RelativeAddressRange src(RelativeAddress(0), 10);
130 E : RelativeAddressRange dst(RelativeAddress(0), 8);
131 E : ASSERT_TRUE(source_map.Push(src, dst));
132 :
133 E : std::vector<OMAP> omap_to;
134 E : BuildOmapVectorFromImageSourceMap(src, source_map, &omap_to);
135 :
136 : // Ensure that every address in the source range gets mapped to some address
137 : // in the destination range.
138 E : for (RelativeAddress rva = src.start(); rva != src.end(); rva += 1) {
139 E : RelativeAddress mapped_rva = pdb::TranslateAddressViaOmap(omap_to, rva);
140 E : EXPECT_TRUE(dst.Contains(mapped_rva, 1));
141 E : }
142 E : }
143 :
144 : } // namespace pe
|