Coverage for /Syzygy/pe/unittest_util.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
97.5%77790.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc.
   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/unittest_util.h"
  16    :  
  17    :  #include <imagehlp.h>
  18    :  
  19    :  #include <algorithm>
  20    :  
  21    :  #include "base/command_line.h"
  22    :  #include "base/file_util.h"
  23    :  #include "base/logging.h"
  24    :  #include "base/path_service.h"
  25    :  #include "base/process_util.h"
  26    :  #include "base/stringprintf.h"
  27    :  #include "base/utf_string_conversions.h"
  28    :  #include "base/win/pe_image.h"
  29    :  #include "gmock/gmock.h"
  30    :  #include "gtest/gtest.h"
  31    :  #include "sawbuck/common/com_utils.h"
  32    :  #include "syzygy/pe/pe_data.h"
  33    :  
  34    :  using pe::CvInfoPdb70;
  35    :  
  36    :  namespace {
  37    :  
  38    :  // This class wraps an HMODULE and ensures that ::FreeLibrary is called when it
  39    :  // goes out of scope.
  40    :  class ScopedHMODULE {
  41    :   public:
  42  E :    explicit ScopedHMODULE(HMODULE v): value_(v) {
  43  E :    }
  44    :  
  45  E :    ~ScopedHMODULE() {
  46  E :      if (value_) {
  47  E :        ::FreeLibrary(value_);
  48    :      }
  49  E :    }
  50    :  
  51  E :    operator HMODULE() const {
  52  E :      return value_;
  53  E :    }
  54    :  
  55    :   private:
  56    :    HMODULE value_;
  57    :  };
  58    :  
  59    :  bool EnumImportsProc(const base::win::PEImage &image,
  60    :                       const char* module,
  61    :                       DWORD ordinal,
  62    :                       const char* name,
  63    :                       DWORD hint,
  64    :                       IMAGE_THUNK_DATA* iat,
  65  E :                       void* cookie) {
  66  E :    DCHECK(module != NULL);
  67  E :    DCHECK(iat != NULL);
  68  E :    DCHECK(cookie != NULL);
  69    :  
  70    :    std::set<std::string>* export_dll_imports =
  71  E :        reinterpret_cast<std::set<std::string>*>(cookie);
  72    :  
  73  E :    if (strcmp(module, "export_dll.dll") == 0) {
  74  E :      if (name != NULL) {
  75  E :        EXPECT_TRUE(export_dll_imports->insert(name).second);
  76  E :      } else {
  77  E :        std::string ordinal_name(base::StringPrintf("#%d", ordinal));
  78  E :        EXPECT_TRUE(export_dll_imports->insert(ordinal_name).second);
  79  E :      }
  80    :    }
  81    :  
  82  E :    return true;
  83  E :  }
  84    :  
  85  E :  void CheckLoadedDllHasSortedSafeSehTable(HMODULE module) {
  86    :    // Verify that the Safe SEH Table is sorted.
  87    :    // http://code.google.com/p/sawbuck/issues/detail?id=42
  88  E :    ASSERT_TRUE(module != NULL);
  89  E :    base::win::PEImage image(module);
  90    :  
  91    :    // Locate the load config directory.
  92    :    PIMAGE_LOAD_CONFIG_DIRECTORY load_config_directory =
  93    :        reinterpret_cast<PIMAGE_LOAD_CONFIG_DIRECTORY>(
  94  E :            image.GetImageDirectoryEntryAddr(IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG));
  95  E :    ASSERT_TRUE(load_config_directory != NULL);
  96    :  
  97    :    // Find the bounds of the Safe SEH Table.
  98    :    DWORD* seh_table_begin =
  99  E :        reinterpret_cast<DWORD*>(load_config_directory->SEHandlerTable);
 100  E :    size_t seh_table_size = load_config_directory->SEHandlerCount;
 101  E :    DWORD* seh_table_end = seh_table_begin + seh_table_size;
 102    :  
 103    :    // Unfortunately, std::is_sorted is an extension pre-c++0x. An equivalent
 104    :    // test is to see if there are any adjacent elements such that the first
 105    :    // is greater than its successor. So, let's look for the first element for
 106    :    // which this is true, and if we get to the end, then there were no such
 107    :    // elements.
 108    :    DWORD* out_of_order_iter = std::adjacent_find(seh_table_begin,
 109    :                                                  seh_table_end,
 110  E :                                                  std::greater<DWORD>());
 111  E :    ASSERT_TRUE(out_of_order_iter == seh_table_end)
 112  E :        << "The Safe SEH Table must be sorted.";
 113  E :  }
 114    :  
 115  E :  void CheckLoadedTestDll(HMODULE module) {
 116    :    // Validate that the DLL is properly constructed.
 117  E :    CheckLoadedDllHasSortedSafeSehTable(module);
 118    :  
 119    :    // Load the exported TestExport function and invoke it.
 120    :    typedef DWORD (WINAPI* TestExportFunc)(size_t buf_len, char* buf);
 121    :    TestExportFunc test_func = reinterpret_cast<TestExportFunc>(
 122  E :        ::GetProcAddress(module, "TestExport"));
 123  E :    ASSERT_TRUE(test_func != NULL);
 124    :  
 125  E :    char buffer[1024] = { 0 };
 126  E :    EXPECT_EQ(0, test_func(arraysize(buffer), buffer));
 127  E :    EXPECT_STREQ("The quick brown fox jumped over the lazy dog", buffer);
 128    :  
 129    :    // Load the exported TestUnusedFunc function and invoke it.
 130    :    typedef void (CALLBACK* TestUnusedFuncs)(HWND, HINSTANCE, LPSTR, int);
 131    :    TestUnusedFuncs test_func2 = reinterpret_cast<TestUnusedFuncs>(
 132  E :        ::GetProcAddress(module, "TestUnusedFuncs"));
 133  E :    ASSERT_TRUE(test_func2 != NULL);
 134  E :    test_func2(0, 0, 0, 0);
 135    :  
 136    :    // Check the image file for sanity.
 137  E :    base::win::PEImage image(module);
 138  E :    ASSERT_TRUE(image.VerifyMagic());
 139    :  
 140  E :    std::set<std::string> export_dll_imports;
 141    :    // Verify all the imports from export_dll.
 142  E :    ASSERT_TRUE(image.EnumAllImports(EnumImportsProc, &export_dll_imports));
 143    :  
 144  E :    std::set<std::string> expected_imports;
 145  E :    expected_imports.insert("function1");
 146  E :    expected_imports.insert("#7");
 147  E :    expected_imports.insert("function3");
 148  E :    EXPECT_THAT(expected_imports, testing::ContainerEq(export_dll_imports));
 149  E :  }
 150    :  
 151    :  }  // namespace
 152    :  
 153    :  namespace testing {
 154    :  
 155    :  const wchar_t PELibUnitTest::kDllName[] = L"test_dll.dll";
 156    :  const wchar_t PELibUnitTest::kDllPdbName[] = L"test_dll.pdb";
 157    :  const wchar_t PELibUnitTest::kRandomizedTestDllName[] =
 158    :      L"randomized_test_dll.dll";
 159    :  const wchar_t PELibUnitTest::kRandomizedTestDllPdbName[] =
 160    :      L"randomized_test_dll.pdb";
 161    :  const wchar_t PELibUnitTest::kRpcInstrumentedDllName[] =
 162    :      L"rpc_instrumented_test_dll.dll";
 163    :  const wchar_t PELibUnitTest::kRpcInstrumentedDllPdbName[] =
 164    :      L"rpc_instrumented_test_dll.pdb";
 165    :  
 166  E :  void PELibUnitTest::CreateTemporaryDir(FilePath* temp_dir) {
 167  E :    ASSERT_TRUE(file_util::CreateNewTempDirectory(L"", temp_dir));
 168  E :    temp_dirs_.push_back(*temp_dir);
 169  E :  }
 170    :  
 171  E :  void PELibUnitTest::TearDown() {
 172  E :    DirList::const_iterator iter;
 173  E :    for (iter = temp_dirs_.begin(); iter != temp_dirs_.end(); ++iter) {
 174  E :      file_util::Delete(*iter, true);
 175  E :    }
 176    :  
 177  E :    Super::TearDown();
 178  E :  }
 179    :  
 180  E :  void PELibUnitTest::CheckTestDll(const FilePath& path) {
 181  E :    LOADED_IMAGE loaded_image = {};
 182    :    BOOL success = ::MapAndLoad(WideToUTF8(path.value()).c_str(),
 183    :                                NULL,
 184    :                                &loaded_image,
 185    :                                FALSE,
 186  E :                                FALSE);
 187  E :    EXPECT_EQ(ERROR_SUCCESS, ::GetLastError());
 188  E :    ASSERT_TRUE(success);
 189  E :    EXPECT_TRUE(::UnMapAndLoad(&loaded_image));
 190    :  
 191  E :    ScopedHMODULE module(::LoadLibrary(path.value().c_str()));
 192  E :    if (module == NULL) {
 193  i :      DWORD error = ::GetLastError();
 194  i :      LOG(ERROR) << "LoadLibrary failed: " << com::LogWe(error);
 195    :    }
 196  E :    ASSERT_TRUE(module != NULL);
 197  E :    CheckLoadedTestDll(module);
 198  E :  }
 199    :  
 200    :  }  // namespace testing

Coverage information generated Thu Sep 06 11:30:46 2012.