| 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> | 
 |    7 #include <vector> | 
|    6  |    8  | 
|    7 #include "testing/gtest/include/gtest/gtest.h" |    9 #include "testing/gtest/include/gtest/gtest.h" | 
|    8 #include "base/win/pe_image.h" |   10 #include "base/win/pe_image.h" | 
|    9 #include "base/win/windows_version.h" |   11 #include "base/win/windows_version.h" | 
|   10  |   12  | 
|   11 namespace base { |   13 namespace base { | 
|   12 namespace win { |   14 namespace win { | 
|   13  |   15  | 
 |   16 namespace { | 
 |   17  | 
 |   18 class Expectations { | 
 |   19  public: | 
 |   20   enum Value { | 
 |   21     sections = 0, | 
 |   22     imports_dlls, | 
 |   23     delay_dlls, | 
 |   24     exports, | 
 |   25     imports, | 
 |   26     delay_imports, | 
 |   27     relocs | 
 |   28   }; | 
 |   29  | 
 |   30   enum Arch { | 
 |   31     ARCH_X86 = 0, | 
 |   32     ARCH_X64, | 
 |   33     ARCH_X86_ON_X64, | 
 |   34     ARCH_X64_ON_X64, | 
 |   35     ARCH_X86_ON_X86, | 
 |   36     ARCH_ALL | 
 |   37   }; | 
 |   38  | 
 |   39   int GetExpectation(Value value); | 
 |   40   void SetOverride(Value value, Version version, Arch arch, int count); | 
 |   41   void SetOverride(Value value, Version version, int count); | 
 |   42   void SetOverride(Value value, Arch arch, int count); | 
 |   43  | 
 |   44   void SetDefault(Value value, int count) { | 
 |   45     SetOverride(value, VERSION_WIN_LAST, ARCH_ALL, count); | 
 |   46   } | 
 |   47  | 
 |   48   Expectations() { | 
 |   49     my_version_ = GetVersion(); | 
 |   50 #if defined(ARCH_CPU_64_BITS) | 
 |   51     my_arch_ = ARCH_X64_ON_X64; | 
 |   52 #else | 
 |   53     OSInfo* os_info = OSInfo::GetInstance(); | 
 |   54     if (os_info->wow64_status() == OSInfo::WOW64_DISABLED) | 
 |   55       my_arch_ = ARCH_X86_ON_X86; | 
 |   56     else | 
 |   57       my_arch_ = ARCH_X86_ON_X64; | 
 |   58 #endif | 
 |   59   } | 
 |   60  | 
 |   61  private: | 
 |   62   class Override { | 
 |   63    public: | 
 |   64     enum MatchType { MATCH_VERSION, MATCH_ARCH, MATCH_BOTH, MATCH_NONE }; | 
 |   65     explicit Override(Value value, Version version, Arch arch, int count) | 
 |   66         : value_(value), version_(version), arch_(arch), count_(count){}; | 
 |   67  | 
 |   68     bool Matches(Value value, Version version, Arch arch, MatchType type) { | 
 |   69       if (value_ != value) | 
 |   70         return false; | 
 |   71       switch (type) { | 
 |   72         case MATCH_BOTH: | 
 |   73           return MatchesVersion(version) && MatchesArch(arch); | 
 |   74           break; | 
 |   75         case MATCH_ARCH: | 
 |   76           return MatchesArch(arch); | 
 |   77           break; | 
 |   78         case MATCH_VERSION: | 
 |   79           return MatchesVersion(version); | 
 |   80           break; | 
 |   81         case MATCH_NONE: | 
 |   82           return true; | 
 |   83           break; | 
 |   84       } | 
 |   85       return false; | 
 |   86     } | 
 |   87  | 
 |   88     int GetCount() { return count_; } | 
 |   89  | 
 |   90    private: | 
 |   91     bool MatchesArch(Arch arch) { | 
 |   92       switch (arch) { | 
 |   93         case ARCH_X64_ON_X64: | 
 |   94           return (arch_ == ARCH_X64_ON_X64 || arch_ == ARCH_X64); | 
 |   95           break; | 
 |   96         case ARCH_X86_ON_X86: | 
 |   97           return (arch_ == ARCH_X86_ON_X86 || arch_ == ARCH_X86); | 
 |   98           break; | 
 |   99         case ARCH_X86_ON_X64: | 
 |  100           return (arch_ == ARCH_X86_ON_X64 || arch_ == ARCH_X86); | 
 |  101           break; | 
 |  102         default: | 
 |  103           return false; | 
 |  104       } | 
 |  105     } | 
 |  106  | 
 |  107     bool MatchesVersion(Version version) { return (version == version_); } | 
 |  108  | 
 |  109     Value value_; | 
 |  110     Version version_; | 
 |  111     Arch arch_; | 
 |  112     int count_; | 
 |  113   }; | 
 |  114  | 
 |  115   bool MatchesMyArch(Arch arch); | 
 |  116  | 
 |  117   std::vector<Override> overrides_; | 
 |  118   Arch my_arch_; | 
 |  119   Version my_version_; | 
 |  120 }; | 
 |  121  | 
 |  122 int Expectations::GetExpectation(Value value) { | 
 |  123   // Prefer OS version specificity over Arch specificity. | 
 |  124   for (auto type : {Expectations::Override::MATCH_BOTH, | 
 |  125                     Expectations::Override::MATCH_VERSION, | 
 |  126                     Expectations::Override::MATCH_ARCH, | 
 |  127                     Expectations::Override::MATCH_NONE}) | 
 |  128     for (auto or : overrides_) | 
 |  129       if (or.Matches(value, my_version_, my_arch_, type)) | 
 |  130         return or.GetCount(); | 
 |  131   return 0; | 
 |  132 } | 
 |  133  | 
 |  134 void Expectations::SetOverride(Value value, | 
 |  135                                Version version, | 
 |  136                                Arch arch, | 
 |  137                                int count) { | 
 |  138   overrides_.push_back(Override(value, version, arch, count)); | 
 |  139 } | 
 |  140  | 
 |  141 void Expectations::SetOverride(Value value, Version version, int count) { | 
 |  142   SetOverride(value, version, ARCH_ALL, count); | 
 |  143 } | 
 |  144  | 
 |  145 void Expectations::SetOverride(Value value, Arch arch, int count) { | 
 |  146   SetOverride(value, VERSION_WIN_LAST, arch, count); | 
 |  147 } | 
 |  148  | 
|   14 // Just counts the number of invocations. |  149 // Just counts the number of invocations. | 
|   15 bool ExportsCallback(const PEImage &image, |  150 bool ExportsCallback(const PEImage &image, | 
|   16                      DWORD ordinal, |  151                      DWORD ordinal, | 
|   17                      DWORD hint, |  152                      DWORD hint, | 
|   18                      LPCSTR name, |  153                      LPCSTR name, | 
|   19                      PVOID function, |  154                      PVOID function, | 
|   20                      LPCSTR forward, |  155                      LPCSTR forward, | 
|   21                      PVOID cookie) { |  156                      PVOID cookie) { | 
|   22   int* count = reinterpret_cast<int*>(cookie); |  157   int* count = reinterpret_cast<int*>(cookie); | 
|   23   (*count)++; |  158   (*count)++; | 
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   76                                PIMAGE_THUNK_DATA name_table, |  211                                PIMAGE_THUNK_DATA name_table, | 
|   77                                PIMAGE_THUNK_DATA iat, |  212                                PIMAGE_THUNK_DATA iat, | 
|   78                                PIMAGE_THUNK_DATA bound_iat, |  213                                PIMAGE_THUNK_DATA bound_iat, | 
|   79                                PIMAGE_THUNK_DATA unload_iat, |  214                                PIMAGE_THUNK_DATA unload_iat, | 
|   80                                PVOID cookie) { |  215                                PVOID cookie) { | 
|   81   int* count = reinterpret_cast<int*>(cookie); |  216   int* count = reinterpret_cast<int*>(cookie); | 
|   82   (*count)++; |  217   (*count)++; | 
|   83   return true; |  218   return true; | 
|   84 } |  219 } | 
|   85  |  220  | 
|   86 // Identifiers for the set of supported expectations. |  221 }  // namespace | 
|   87 enum ExpectationSet { |  | 
|   88   WIN_2K_SET, |  | 
|   89   WIN_XP_SET, |  | 
|   90   WIN_VISTA_SET, |  | 
|   91   WIN_7_SET, |  | 
|   92   WIN_8_SET, |  | 
|   93   UNSUPPORTED_SET, |  | 
|   94 }; |  | 
|   95  |  | 
|   96 // We'll be using some known values for the tests. |  | 
|   97 enum Value { |  | 
|   98   sections = 0, |  | 
|   99   imports_dlls, |  | 
|  100   delay_dlls, |  | 
|  101   exports, |  | 
|  102   imports, |  | 
|  103   delay_imports, |  | 
|  104   relocs |  | 
|  105 }; |  | 
|  106  |  | 
|  107 ExpectationSet GetExpectationSet(DWORD os) { |  | 
|  108   if (os == 50) |  | 
|  109     return WIN_2K_SET; |  | 
|  110   if (os == 51) |  | 
|  111     return WIN_XP_SET; |  | 
|  112   if (os == 60) |  | 
|  113     return WIN_VISTA_SET; |  | 
|  114   if (os == 61) |  | 
|  115     return WIN_7_SET; |  | 
|  116   if (os >= 62) |  | 
|  117     return WIN_8_SET; |  | 
|  118   return UNSUPPORTED_SET; |  | 
|  119 } |  | 
|  120  |  | 
|  121 // Retrieves the expected value from advapi32.dll based on the OS. |  | 
|  122 int GetExpectedValue(Value value, DWORD os) { |  | 
|  123   const int xp_delay_dlls = 2; |  | 
|  124   const int xp_exports = 675; |  | 
|  125   const int xp_imports = 422; |  | 
|  126   const int xp_delay_imports = 8; |  | 
|  127   const int xp_relocs = 9180; |  | 
|  128   const int vista_delay_dlls = 4; |  | 
|  129   const int vista_exports = 799; |  | 
|  130   const int vista_imports = 476; |  | 
|  131   const int vista_delay_imports = 24; |  | 
|  132   const int vista_relocs = 10188; |  | 
|  133   const int w2k_delay_dlls = 0; |  | 
|  134   const int w2k_exports = 566; |  | 
|  135   const int w2k_imports = 357; |  | 
|  136   const int w2k_delay_imports = 0; |  | 
|  137   const int w2k_relocs = 7388; |  | 
|  138   const int win7_delay_dlls = 7; |  | 
|  139   const int win7_exports = 806; |  | 
|  140   const int win7_imports = 568; |  | 
|  141   const int win7_delay_imports = 71; |  | 
|  142   int win7_relocs = 7812; |  | 
|  143   int win7_sections = 4; |  | 
|  144   const int win8_delay_dlls = 9; |  | 
|  145   const int win8_exports = 806; |  | 
|  146   const int win8_imports = 568; |  | 
|  147   const int win8_delay_imports = 113; |  | 
|  148   const int win8_relocs = 9478; |  | 
|  149   int win8_sections = 4; |  | 
|  150   int win8_import_dlls = 17; |  | 
|  151  |  | 
|  152   base::win::OSInfo* os_info = base::win::OSInfo::GetInstance(); |  | 
|  153   // 32-bit process on a 32-bit system. |  | 
|  154   if (os_info->architecture() == base::win::OSInfo::X86_ARCHITECTURE) { |  | 
|  155     win8_sections = 5; |  | 
|  156     win8_import_dlls = 19; |  | 
|  157  |  | 
|  158   // 64-bit process on a 64-bit system. |  | 
|  159   } else if (os_info->wow64_status() == base::win::OSInfo::WOW64_DISABLED) { |  | 
|  160     win7_sections = 6; |  | 
|  161     win7_relocs = 2712; |  | 
|  162   } |  | 
|  163  |  | 
|  164   // Contains the expected value, for each enumerated property (Value), and the |  | 
|  165   // OS version: [Value][os_version] |  | 
|  166   const int expected[][5] = { |  | 
|  167     {4, 4, 4, win7_sections, win8_sections}, |  | 
|  168     {3, 3, 3, 13, win8_import_dlls}, |  | 
|  169     {w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls, win7_delay_dlls, |  | 
|  170      win8_delay_dlls}, |  | 
|  171     {w2k_exports, xp_exports, vista_exports, win7_exports, win8_exports}, |  | 
|  172     {w2k_imports, xp_imports, vista_imports, win7_imports, win8_imports}, |  | 
|  173     {w2k_delay_imports, xp_delay_imports, |  | 
|  174      vista_delay_imports, win7_delay_imports, win8_delay_imports}, |  | 
|  175     {w2k_relocs, xp_relocs, vista_relocs, win7_relocs, win8_relocs} |  | 
|  176   }; |  | 
|  177   COMPILE_ASSERT(arraysize(expected[0]) == UNSUPPORTED_SET, |  | 
|  178                  expected_value_set_mismatch); |  | 
|  179  |  | 
|  180   if (value > relocs) |  | 
|  181     return 0; |  | 
|  182   ExpectationSet expected_set = GetExpectationSet(os); |  | 
|  183   if (expected_set >= arraysize(expected)) { |  | 
|  184     // This should never happen.  Log a failure if it does. |  | 
|  185     EXPECT_NE(UNSUPPORTED_SET, expected_set); |  | 
|  186     expected_set = WIN_2K_SET; |  | 
|  187   } |  | 
|  188  |  | 
|  189   return expected[value][expected_set]; |  | 
|  190 } |  | 
|  191  |  | 
|  192  |  | 
|  193 // TODO(jschuh): crbug.com/167707 Need to fix test on Win64 bots |  | 
|  194 #if defined(OS_WIN) && defined(ARCH_CPU_X86_64) |  | 
|  195 #define MAYBE_EnumeratesPE DISABLED_EnumeratesPE |  | 
|  196 #else |  | 
|  197 #define MAYBE_EnumeratesPE EnumeratesPE |  | 
|  198 #endif |  | 
|  199  |  222  | 
|  200 // Tests that we are able to enumerate stuff from a PE file, and that |  223 // Tests that we are able to enumerate stuff from a PE file, and that | 
|  201 // the actual number of items found is within the expected range. |  224 // the actual number of items found is within the expected range. | 
|  202 TEST(PEImageTest, MAYBE_EnumeratesPE) { |  225 TEST(PEImageTest, EnumeratesPE) { | 
|  203   HMODULE module = LoadLibrary(L"advapi32.dll"); |  226   Expectations expectations; | 
 |  227  | 
 |  228   // Default expectations. | 
 |  229   expectations.SetDefault(Expectations::sections, 5); | 
 |  230   expectations.SetDefault(Expectations::imports_dlls, 1); | 
 |  231   expectations.SetDefault(Expectations::delay_dlls, 1); | 
 |  232   expectations.SetDefault(Expectations::exports, 1); | 
 |  233   expectations.SetDefault(Expectations::imports, 63); | 
 |  234   expectations.SetDefault(Expectations::delay_imports, 2); | 
 |  235   expectations.SetDefault(Expectations::relocs, 1584); | 
 |  236  | 
 |  237   // win_chromium_x64_rel_ng (Win7 x64 on x64) | 
 |  238   expectations.SetOverride(Expectations::sections, VERSION_WIN7, | 
 |  239                            Expectations::ARCH_X64, 6); | 
 |  240   expectations.SetOverride(Expectations::imports, VERSION_WIN7, | 
 |  241                            Expectations::ARCH_X64, 66); | 
 |  242   expectations.SetOverride(Expectations::relocs, VERSION_WIN7, | 
 |  243                            Expectations::ARCH_X64, 630); | 
 |  244  | 
 |  245   HMODULE module = LoadLibrary(L"pe_image_test.dll"); | 
|  204   ASSERT_TRUE(NULL != module); |  246   ASSERT_TRUE(NULL != module); | 
|  205  |  247  | 
|  206   PEImage pe(module); |  248   PEImage pe(module); | 
|  207   int count = 0; |  249   int count = 0; | 
|  208   EXPECT_TRUE(pe.VerifyMagic()); |  250   EXPECT_TRUE(pe.VerifyMagic()); | 
|  209  |  251  | 
|  210   DWORD os = pe.GetNTHeaders()->OptionalHeader.MajorOperatingSystemVersion; |  | 
|  211   os = os * 10 + pe.GetNTHeaders()->OptionalHeader.MinorOperatingSystemVersion; |  | 
|  212  |  | 
|  213   // Skip this test for unsupported OS versions. |  | 
|  214   if (GetExpectationSet(os) == UNSUPPORTED_SET) |  | 
|  215     return; |  | 
|  216  |  | 
|  217   pe.EnumSections(SectionsCallback, &count); |  252   pe.EnumSections(SectionsCallback, &count); | 
|  218   EXPECT_EQ(GetExpectedValue(sections, os), count); |  253   EXPECT_EQ(expectations.GetExpectation(Expectations::sections), count); | 
|  219  |  254  | 
|  220   count = 0; |  255   count = 0; | 
|  221   pe.EnumImportChunks(ImportChunksCallback, &count); |  256   pe.EnumImportChunks(ImportChunksCallback, &count); | 
|  222   EXPECT_EQ(GetExpectedValue(imports_dlls, os), count); |  257   EXPECT_EQ(expectations.GetExpectation(Expectations::imports_dlls), count); | 
|  223  |  258  | 
|  224   count = 0; |  259   count = 0; | 
|  225   pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); |  260   pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); | 
|  226   EXPECT_EQ(GetExpectedValue(delay_dlls, os), count); |  261   EXPECT_EQ(expectations.GetExpectation(Expectations::delay_dlls), count); | 
|  227  |  262  | 
|  228   count = 0; |  263   count = 0; | 
|  229   pe.EnumExports(ExportsCallback, &count); |  264   pe.EnumExports(ExportsCallback, &count); | 
|  230   EXPECT_GT(count, GetExpectedValue(exports, os) - 20); |  265   EXPECT_EQ(expectations.GetExpectation(Expectations::exports), count); | 
|  231   EXPECT_LT(count, GetExpectedValue(exports, os) + 100); |  | 
|  232  |  266  | 
|  233   count = 0; |  267   count = 0; | 
|  234   pe.EnumAllImports(ImportsCallback, &count); |  268   pe.EnumAllImports(ImportsCallback, &count); | 
|  235   EXPECT_GT(count, GetExpectedValue(imports, os) - 20); |  269   EXPECT_EQ(expectations.GetExpectation(Expectations::imports), count); | 
|  236   EXPECT_LT(count, GetExpectedValue(imports, os) + 100); |  | 
|  237  |  270  | 
|  238   count = 0; |  271   count = 0; | 
|  239   pe.EnumAllDelayImports(ImportsCallback, &count); |  272   pe.EnumAllDelayImports(ImportsCallback, &count); | 
|  240   EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2); |  273   EXPECT_EQ(expectations.GetExpectation(Expectations::delay_imports), count); | 
|  241   EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8); |  | 
|  242  |  274  | 
|  243   count = 0; |  275   count = 0; | 
|  244   pe.EnumRelocs(RelocsCallback, &count); |  276   pe.EnumRelocs(RelocsCallback, &count); | 
|  245   EXPECT_GT(count, GetExpectedValue(relocs, os) - 150); |  277   EXPECT_EQ(expectations.GetExpectation(Expectations::relocs), count); | 
|  246   EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500); |  | 
|  247  |  278  | 
|  248   FreeLibrary(module); |  279   FreeLibrary(module); | 
|  249 } |  280 } | 
|  250  |  281  | 
|  251 // Tests that we can locate an specific exported symbol, by name and by ordinal. |  282 // Tests that we can locate an specific exported symbol, by name and by ordinal. | 
|  252 TEST(PEImageTest, RetrievesExports) { |  283 TEST(PEImageTest, RetrievesExports) { | 
|  253   HMODULE module = LoadLibrary(L"advapi32.dll"); |  284   HMODULE module = LoadLibrary(L"advapi32.dll"); | 
|  254   ASSERT_TRUE(NULL != module); |  285   ASSERT_TRUE(NULL != module); | 
|  255  |  286  | 
|  256   PEImage pe(module); |  287   PEImage pe(module); | 
| (...skipping 21 matching lines...) Expand all  Loading... | 
|  278   EXPECT_TRUE(pe.GetDebugId(&guid, &age)); |  309   EXPECT_TRUE(pe.GetDebugId(&guid, &age)); | 
|  279  |  310  | 
|  280   GUID empty_guid = {0}; |  311   GUID empty_guid = {0}; | 
|  281   EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); |  312   EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); | 
|  282   EXPECT_NE(0U, age); |  313   EXPECT_NE(0U, age); | 
|  283   FreeLibrary(module); |  314   FreeLibrary(module); | 
|  284 } |  315 } | 
|  285  |  316  | 
|  286 }  // namespace win |  317 }  // namespace win | 
|  287 }  // namespace base |  318 }  // namespace base | 
| OLD | NEW |