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/coff_file.h"
16 :
17 : #include "gtest/gtest.h"
18 : #include "syzygy/core/unittest_util.h"
19 : #include "syzygy/pe/unittest_util.h"
20 :
21 : namespace pe {
22 :
23 : namespace {
24 :
25 : using core::AbsoluteAddress;
26 : using core::FileOffsetAddress;
27 : using core::RelativeAddress;
28 :
29 : class CoffFileTest : public testing::PELibUnitTest {
30 : typedef testing::PELibUnitTest Super;
31 :
32 : public:
33 E : CoffFileTest() {
34 E : }
35 :
36 E : virtual void SetUp() override {
37 E : Super::SetUp();
38 :
39 : test_dll_obj_path_ =
40 E : testing::GetExeTestDataRelativePath(testing::kTestDllCoffObjName);
41 E : }
42 :
43 : protected:
44 : base::FilePath test_dll_obj_path_;
45 : CoffFile image_file_;
46 :
47 : DISALLOW_COPY_AND_ASSIGN(CoffFileTest);
48 : };
49 :
50 : const char kTestExportPrefix[] = "?TestExport@@";
51 : const char kTestStaticPrefix[] = "?TestStatic@@";
52 :
53 : } // namespace
54 :
55 E : TEST_F(CoffFileTest, Init) {
56 E : EXPECT_TRUE(image_file_.file_header() == NULL);
57 E : EXPECT_TRUE(image_file_.section_headers() == NULL);
58 E : EXPECT_TRUE(image_file_.symbols() == NULL);
59 E : EXPECT_TRUE(image_file_.strings() == NULL);
60 :
61 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
62 :
63 E : EXPECT_TRUE(image_file_.file_header() != NULL);
64 E : EXPECT_TRUE(image_file_.section_headers() != NULL);
65 E : EXPECT_TRUE(image_file_.symbols() != NULL);
66 E : EXPECT_TRUE(image_file_.strings() != NULL);
67 :
68 E : EXPECT_TRUE(image_file_.file_header()->PointerToSymbolTable != 0);
69 :
70 : // Technically, SizeOfOptionalHeader could be non-zero, but it is
71 : // deprecated and MSVC should not generate such a header.
72 E : EXPECT_EQ(0u, image_file_.file_header()->SizeOfOptionalHeader);
73 E : }
74 :
75 E : TEST_F(CoffFileTest, TranslateSectionOffsets) {
76 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
77 :
78 E : size_t num_sections = image_file_.file_header()->NumberOfSections;
79 E : for (size_t i = 0; i < num_sections; ++i) {
80 E : const IMAGE_SECTION_HEADER* header = image_file_.section_header(i);
81 E : if (!image_file_.IsSectionMapped(i))
82 E : continue;
83 :
84 E : size_t offset = header->SizeOfRawData / 2;
85 E : FileOffsetAddress addr(FileOffsetAddress::kInvalidAddress);
86 E : ASSERT_TRUE(image_file_.SectionOffsetToFileOffset(i, offset, &addr));
87 E : EXPECT_NE(addr, FileOffsetAddress::kInvalidAddress);
88 :
89 E : size_t new_section_index = kInvalidSection;
90 E : size_t new_offset = SIZE_MAX;
91 : ASSERT_TRUE(image_file_.FileOffsetToSectionOffset(
92 E : addr, &new_section_index, &new_offset));
93 E : EXPECT_EQ(i, new_section_index);
94 E : EXPECT_EQ(offset, new_offset);
95 E : }
96 E : }
97 :
98 E : TEST_F(CoffFileTest, GetSymbols) {
99 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
100 :
101 E : size_t num_symbols = image_file_.file_header()->NumberOfSymbols;
102 E : EXPECT_GT(num_symbols, 0u);
103 E : for (size_t i = 0; i < num_symbols; ++i) {
104 E : EXPECT_TRUE(image_file_.symbol(i) != NULL);
105 E : }
106 E : }
107 :
108 E : TEST_F(CoffFileTest, DecodeRelocs) {
109 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
110 :
111 E : CoffFile::RelocMap reloc_map;
112 E : image_file_.DecodeRelocs(&reloc_map);
113 E : EXPECT_FALSE(reloc_map.empty());
114 :
115 : // Validate relocations.
116 E : CoffFile::RelocMap::const_iterator it = reloc_map.begin();
117 E : for (; it != reloc_map.end(); ++it) {
118 : // Location to relocate must be mapped within the address space.
119 E : EXPECT_TRUE(image_file_.Contains(it->first, sizeof(void*)));
120 :
121 : // Relocation must reference a valid symbol.
122 E : EXPECT_TRUE(image_file_.symbol(it->second->SymbolTableIndex) != NULL);
123 E : }
124 E : }
125 :
126 E : TEST_F(CoffFileTest, GetSymbolName) {
127 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
128 :
129 E : size_t num_symbols = image_file_.file_header()->NumberOfSymbols;
130 E : const IMAGE_SYMBOL* symbol = NULL;
131 E : for (size_t i = 0; i < num_symbols; i += 1 + symbol->NumberOfAuxSymbols) {
132 E : symbol = image_file_.symbol(i);
133 E : EXPECT_TRUE(image_file_.GetSymbolName(i) != NULL);
134 E : }
135 E : }
136 :
137 E : TEST_F(CoffFileTest, HaveTestSymbols) {
138 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
139 :
140 E : bool have_dll_main = false;
141 E : bool have_test_export = false;
142 E : size_t num_symbols = image_file_.file_header()->NumberOfSymbols;
143 E : const IMAGE_SYMBOL* symbol = NULL;
144 E : for (size_t i = 0; i < num_symbols; i += 1 + symbol->NumberOfAuxSymbols) {
145 E : symbol = image_file_.symbol(i);
146 E : const char* symbol_name = image_file_.GetSymbolName(i);
147 E : if (strcmp(symbol_name, "_DllMain@12") == 0)
148 E : have_dll_main = true;
149 : if (strncmp(symbol_name, kTestExportPrefix,
150 E : strlen(kTestExportPrefix)) == 0)
151 E : have_test_export = true;
152 E : }
153 E : EXPECT_TRUE(have_dll_main);
154 E : EXPECT_TRUE(have_test_export);
155 E : }
156 :
157 E : TEST_F(CoffFileTest, HaveStaticFunction) {
158 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
159 :
160 E : const IMAGE_SYMBOL* test_static_symbol = NULL;
161 E : size_t num_symbols = image_file_.file_header()->NumberOfSymbols;
162 E : const IMAGE_SYMBOL* symbol = NULL;
163 E : for (size_t i = 0; i < num_symbols; i += 1 + symbol->NumberOfAuxSymbols) {
164 E : symbol = image_file_.symbol(i);
165 E : const char* symbol_name = image_file_.GetSymbolName(i);
166 : if (strncmp(symbol_name, kTestStaticPrefix,
167 E : strlen(kTestStaticPrefix)) == 0) {
168 E : test_static_symbol = image_file_.symbol(i);
169 E : break;
170 : }
171 E : }
172 E : ASSERT_TRUE(test_static_symbol != NULL);
173 E : ASSERT_EQ(0u, test_static_symbol->NumberOfAuxSymbols);
174 E : }
175 :
176 E : TEST_F(CoffFileTest, HaveFunctionAndLabels) {
177 E : ASSERT_TRUE(image_file_.Init(test_dll_obj_path_));
178 :
179 E : size_t num_functions = 0;
180 E : size_t num_labels = 0;
181 E : size_t num_symbols = image_file_.file_header()->NumberOfSymbols;
182 E : const IMAGE_SYMBOL* symbol = NULL;
183 E : for (size_t i = 0; i < num_symbols; i += 1 + symbol->NumberOfAuxSymbols) {
184 E : symbol = image_file_.symbol(i);
185 E : const IMAGE_SYMBOL* symbol = image_file_.symbol(i);
186 : // Specifications say the DTYPE is in the MSB but it's really only
187 : // shifted by 4, not 8.
188 E : num_functions += symbol->Type >> 4 == IMAGE_SYM_DTYPE_FUNCTION;
189 E : num_labels += symbol->StorageClass == IMAGE_SYM_CLASS_LABEL;
190 E : }
191 E : ASSERT_LT(0u, num_functions);
192 E : ASSERT_LT(0u, num_labels);
193 E : }
194 :
195 E : TEST(SimpleCoffFileTest, InitCodeView2Symbols) {
196 E : base::FilePath path = testing::GetSrcRelativePath(testing::kCodeView2Name);
197 E : CoffFile file;
198 E : EXPECT_TRUE(file.Init(path));
199 E : }
200 :
201 E : TEST(SimpleCoffFileTest, InitEmptyStringTable) {
202 : base::FilePath path = testing::GetSrcRelativePath(
203 E : testing::kEmptyStringTableCoffName);
204 E : CoffFile file;
205 E : EXPECT_TRUE(file.Init(path));
206 E : }
207 :
208 : } // namespace pe
|