| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 // This file contains unit tests for PEImage. | 5 // This file contains unit tests for PEImage. |
| 6 #include <algorithm> | 6 #include <algorithm> |
| 7 #include <vector> | 7 #include <vector> |
| 8 | 8 |
| 9 #include "base/files/file_path.h" |
| 10 #include "base/path_service.h" |
| 11 #include "base/win/pe_image.h" |
| 9 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
| 10 #include "base/win/pe_image.h" | |
| 11 #include "base/win/windows_version.h" | |
| 12 | |
| 13 namespace { | |
| 14 | |
| 15 class Expectations { | |
| 16 public: | |
| 17 enum Value { | |
| 18 SECTIONS = 0, | |
| 19 IMPORTS_DLLS, | |
| 20 DELAY_DLLS, | |
| 21 EXPORTS, | |
| 22 IMPORTS, | |
| 23 DELAY_IMPORTS, | |
| 24 RELOCS | |
| 25 }; | |
| 26 | |
| 27 enum Arch { | |
| 28 ARCH_X86 = 0, | |
| 29 ARCH_X64, | |
| 30 ARCH_ALL | |
| 31 }; | |
| 32 | |
| 33 Expectations(); | |
| 34 | |
| 35 void SetDefault(Value value, int count); | |
| 36 void SetOverride(Value value, base::win::Version version, | |
| 37 Arch arch, int count); | |
| 38 void SetOverride(Value value, base::win::Version version, int count); | |
| 39 void SetOverride(Value value, Arch arch, int count); | |
| 40 | |
| 41 // returns -1 on failure. | |
| 42 int GetExpectation(Value value); | |
| 43 | |
| 44 private: | |
| 45 class Override { | |
| 46 public: | |
| 47 enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE }; | |
| 48 | |
| 49 Override(Value value, base::win::Version version, Arch arch, int count) | |
| 50 : value_(value), version_(version), arch_(arch), count_(count) { | |
| 51 }; | |
| 52 | |
| 53 bool Matches(Value value, base::win::Version version, | |
| 54 Arch arch, MatchType type) { | |
| 55 if (value_ != value) | |
| 56 return false; | |
| 57 | |
| 58 switch (type) { | |
| 59 case MATCH_BOTH: | |
| 60 return (arch == arch_ && version == version_); | |
| 61 case MATCH_ARCH: | |
| 62 return (arch == arch_ && version_ == base::win::VERSION_WIN_LAST); | |
| 63 case MATCH_VERSION: | |
| 64 return (arch_ == ARCH_ALL && version == version_); | |
| 65 case MATCH_NONE: | |
| 66 return (arch_ == ARCH_ALL && version_ == base::win::VERSION_WIN_LAST); | |
| 67 } | |
| 68 return false; | |
| 69 } | |
| 70 | |
| 71 int GetCount() { return count_; } | |
| 72 | |
| 73 private: | |
| 74 Value value_; | |
| 75 base::win::Version version_; | |
| 76 Arch arch_; | |
| 77 int count_; | |
| 78 }; | |
| 79 | |
| 80 bool MatchesMyArch(Arch arch); | |
| 81 | |
| 82 std::vector<Override> overrides_; | |
| 83 Arch my_arch_; | |
| 84 base::win::Version my_version_; | |
| 85 }; | |
| 86 | |
| 87 Expectations::Expectations() { | |
| 88 my_version_ = base::win::GetVersion(); | |
| 89 #if defined(ARCH_CPU_64_BITS) | |
| 90 my_arch_ = ARCH_X64; | |
| 91 #else | |
| 92 my_arch_ = ARCH_X86; | |
| 93 #endif | |
| 94 } | |
| 95 | |
| 96 int Expectations::GetExpectation(Value value) { | |
| 97 // Prefer OS version specificity over Arch specificity. | |
| 98 for (auto type : { Override::MATCH_BOTH, | |
| 99 Override::MATCH_VERSION, | |
| 100 Override::MATCH_ARCH, | |
| 101 Override::MATCH_NONE }) { | |
| 102 for (auto override : overrides_) { | |
| 103 if (override.Matches(value, my_version_, my_arch_, type)) | |
| 104 return override.GetCount(); | |
| 105 } | |
| 106 } | |
| 107 return -1; | |
| 108 } | |
| 109 | |
| 110 void Expectations::SetDefault(Value value, int count) { | |
| 111 SetOverride(value, base::win::VERSION_WIN_LAST, ARCH_ALL, count); | |
| 112 } | |
| 113 | |
| 114 void Expectations::SetOverride(Value value, | |
| 115 base::win::Version version, | |
| 116 Arch arch, | |
| 117 int count) { | |
| 118 overrides_.push_back(Override(value, version, arch, count)); | |
| 119 } | |
| 120 | |
| 121 void Expectations::SetOverride(Value value, | |
| 122 base::win::Version version, | |
| 123 int count) { | |
| 124 SetOverride(value, version, ARCH_ALL, count); | |
| 125 } | |
| 126 | |
| 127 void Expectations::SetOverride(Value value, Arch arch, int count) { | |
| 128 SetOverride(value, base::win::VERSION_WIN_LAST, arch, count); | |
| 129 } | |
| 130 | |
| 131 } // namespace | |
| 132 | 13 |
| 133 namespace base { | 14 namespace base { |
| 134 namespace win { | 15 namespace win { |
| 135 | 16 |
| 136 namespace { | 17 namespace { |
| 137 | 18 |
| 138 // Just counts the number of invocations. | 19 // Just counts the number of invocations. |
| 139 bool ImportsCallback(const PEImage& image, | 20 bool ImportsCallback(const PEImage& image, |
| 140 LPCSTR module, | 21 LPCSTR module, |
| 141 DWORD ordinal, | 22 DWORD ordinal, |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 LPCSTR forward, | 84 LPCSTR forward, |
| 204 PVOID cookie) { | 85 PVOID cookie) { |
| 205 int* count = reinterpret_cast<int*>(cookie); | 86 int* count = reinterpret_cast<int*>(cookie); |
| 206 (*count)++; | 87 (*count)++; |
| 207 return true; | 88 return true; |
| 208 } | 89 } |
| 209 | 90 |
| 210 } // namespace | 91 } // namespace |
| 211 | 92 |
| 212 // Tests that we are able to enumerate stuff from a PE file, and that | 93 // Tests that we are able to enumerate stuff from a PE file, and that |
| 213 // the actual number of items found is within the expected range. | 94 // the actual number of items found matches an expected value. |
| 214 TEST(PEImageTest, EnumeratesPE) { | 95 TEST(PEImageTest, EnumeratesPE) { |
| 215 Expectations expectations; | 96 base::FilePath pe_image_test_path; |
| 97 ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &pe_image_test_path)); |
| 98 pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image")); |
| 216 | 99 |
| 217 #ifndef NDEBUG | 100 #if defined(ARCH_CPU_64_BITS) |
| 218 // Default Debug expectations. | 101 pe_image_test_path = |
| 219 expectations.SetDefault(Expectations::SECTIONS, 7); | 102 pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_64.dll")); |
| 220 expectations.SetDefault(Expectations::IMPORTS_DLLS, 3); | 103 const int sections = 6; |
| 221 expectations.SetDefault(Expectations::DELAY_DLLS, 2); | 104 const int imports_dlls = 2; |
| 222 expectations.SetDefault(Expectations::EXPORTS, 2); | 105 const int delay_dlls = 2; |
| 223 expectations.SetDefault(Expectations::IMPORTS, 49); | 106 const int exports = 2; |
| 224 expectations.SetDefault(Expectations::DELAY_IMPORTS, 2); | 107 const int imports = 69; |
| 225 expectations.SetDefault(Expectations::RELOCS, 438); | 108 const int delay_imports = 2; |
| 226 | 109 const int relocs = 632; |
| 227 // 64-bit Debug expectations. | |
| 228 expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 8); | |
| 229 expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69); | |
| 230 expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632); | |
| 231 #else | 110 #else |
| 232 // Default Release expectations. | 111 pe_image_test_path = |
| 233 expectations.SetDefault(Expectations::SECTIONS, 5); | 112 pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_32.dll")); |
| 234 expectations.SetDefault(Expectations::IMPORTS_DLLS, 2); | 113 const int sections = 5; |
| 235 expectations.SetDefault(Expectations::DELAY_DLLS, 2); | 114 const int imports_dlls = 2; |
| 236 expectations.SetDefault(Expectations::EXPORTS, 2); | 115 const int delay_dlls = 2; |
| 237 expectations.SetDefault(Expectations::IMPORTS, 66); | 116 const int exports = 2; |
| 238 expectations.SetDefault(Expectations::DELAY_IMPORTS, 2); | 117 const int imports = 66; |
| 239 expectations.SetDefault(Expectations::RELOCS, 1586); | 118 const int delay_imports = 2; |
| 240 | 119 const int relocs = 1586; |
| 241 // 64-bit Release expectations. | |
| 242 expectations.SetOverride(Expectations::SECTIONS, Expectations::ARCH_X64, 6); | |
| 243 expectations.SetOverride(Expectations::IMPORTS, Expectations::ARCH_X64, 69); | |
| 244 expectations.SetOverride(Expectations::RELOCS, Expectations::ARCH_X64, 632); | |
| 245 #endif | 120 #endif |
| 246 | 121 |
| 247 HMODULE module = LoadLibrary(L"pe_image_test.dll"); | 122 HMODULE module = LoadLibrary(pe_image_test_path.value().c_str()); |
| 248 ASSERT_TRUE(NULL != module); | 123 ASSERT_TRUE(NULL != module); |
| 249 | 124 |
| 250 PEImage pe(module); | 125 PEImage pe(module); |
| 251 int count = 0; | 126 int count = 0; |
| 252 EXPECT_TRUE(pe.VerifyMagic()); | 127 EXPECT_TRUE(pe.VerifyMagic()); |
| 253 | 128 |
| 254 pe.EnumSections(SectionsCallback, &count); | 129 pe.EnumSections(SectionsCallback, &count); |
| 255 EXPECT_EQ(expectations.GetExpectation(Expectations::SECTIONS), count); | 130 EXPECT_EQ(sections, count); |
| 256 | 131 |
| 257 count = 0; | 132 count = 0; |
| 258 pe.EnumImportChunks(ImportChunksCallback, &count); | 133 pe.EnumImportChunks(ImportChunksCallback, &count); |
| 259 EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS_DLLS), count); | 134 EXPECT_EQ(imports_dlls, count); |
| 260 | 135 |
| 261 count = 0; | 136 count = 0; |
| 262 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); | 137 pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); |
| 263 EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_DLLS), count); | 138 EXPECT_EQ(delay_dlls, count); |
| 264 | 139 |
| 265 count = 0; | 140 count = 0; |
| 266 pe.EnumExports(ExportsCallback, &count); | 141 pe.EnumExports(ExportsCallback, &count); |
| 267 EXPECT_EQ(expectations.GetExpectation(Expectations::EXPORTS), count); | 142 EXPECT_EQ(exports, count); |
| 268 | 143 |
| 269 count = 0; | 144 count = 0; |
| 270 pe.EnumAllImports(ImportsCallback, &count); | 145 pe.EnumAllImports(ImportsCallback, &count); |
| 271 EXPECT_EQ(expectations.GetExpectation(Expectations::IMPORTS), count); | 146 EXPECT_EQ(imports, count); |
| 272 | 147 |
| 273 count = 0; | 148 count = 0; |
| 274 pe.EnumAllDelayImports(ImportsCallback, &count); | 149 pe.EnumAllDelayImports(ImportsCallback, &count); |
| 275 EXPECT_EQ(expectations.GetExpectation(Expectations::DELAY_IMPORTS), count); | 150 EXPECT_EQ(delay_imports, count); |
| 276 | 151 |
| 277 count = 0; | 152 count = 0; |
| 278 pe.EnumRelocs(RelocsCallback, &count); | 153 pe.EnumRelocs(RelocsCallback, &count); |
| 279 EXPECT_EQ(expectations.GetExpectation(Expectations::RELOCS), count); | 154 EXPECT_EQ(relocs, count); |
| 280 | 155 |
| 281 FreeLibrary(module); | 156 FreeLibrary(module); |
| 282 } | 157 } |
| 283 | 158 |
| 284 // Tests that we can locate an specific exported symbol, by name and by ordinal. | 159 // Tests that we can locate an specific exported symbol, by name and by ordinal. |
| 285 TEST(PEImageTest, RetrievesExports) { | 160 TEST(PEImageTest, RetrievesExports) { |
| 286 HMODULE module = LoadLibrary(L"advapi32.dll"); | 161 HMODULE module = LoadLibrary(L"advapi32.dll"); |
| 287 ASSERT_TRUE(NULL != module); | 162 ASSERT_TRUE(NULL != module); |
| 288 | 163 |
| 289 PEImage pe(module); | 164 PEImage pe(module); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 311 EXPECT_TRUE(pe.GetDebugId(&guid, &age)); | 186 EXPECT_TRUE(pe.GetDebugId(&guid, &age)); |
| 312 | 187 |
| 313 GUID empty_guid = {0}; | 188 GUID empty_guid = {0}; |
| 314 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); | 189 EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); |
| 315 EXPECT_NE(0U, age); | 190 EXPECT_NE(0U, age); |
| 316 FreeLibrary(module); | 191 FreeLibrary(module); |
| 317 } | 192 } |
| 318 | 193 |
| 319 } // namespace win | 194 } // namespace win |
| 320 } // namespace base | 195 } // namespace base |
| OLD | NEW |