Coverage for /Syzygy/pe/pe_coff_file_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
95.6%1291350.C++test

Line-by-line coverage:

   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/pe_coff_file.h"
  16    :  
  17    :  #include "base/native_library.h"
  18    :  #include "base/path_service.h"
  19    :  #include "base/files/file_path.h"
  20    :  #include "base/strings/string_util.h"
  21    :  #include "gmock/gmock.h"
  22    :  #include "gtest/gtest.h"
  23    :  #include "syzygy/core/unittest_util.h"
  24    :  #include "syzygy/pe/unittest_util.h"
  25    :  
  26    :  namespace pe {
  27    :  
  28    :  namespace {
  29    :  
  30    :  using core::AbsoluteAddress;
  31    :  using core::FileOffsetAddress;
  32    :  using core::RelativeAddress;
  33    :  
  34    :  template <typename AddressSpaceTraits>
  35    :  class TestPECoffFile : public PECoffFile<AddressSpaceTraits> {
  36    :   public:
  37    :    // Partial initialization, for common parts.
  38  E :    bool Init(const base::FilePath& path, bool has_pe_headers) {
  39  E :      PECoffFile::Init(path);
  40    :  
  41  E :      FILE* file = base::OpenFile(path, "rb");
  42  E :      if (file == NULL) {
  43  i :        LOG(ERROR) << "Failed to open file " << path.value() << ".";
  44  i :        return false;
  45    :      }
  46    :  
  47  E :      FileOffsetAddress file_header_start(0);
  48  E :      if (has_pe_headers) {
  49    :        // Read NT header position at 0x3C according to the spec.
  50  E :        uint32 nt_header_pos = 0;
  51  E :        if (!ReadAt(file, 0x3C, &nt_header_pos, sizeof(nt_header_pos))) {
  52  i :          LOG(ERROR) << "Unable to read NT header offset.";
  53  i :          return false;
  54    :        }
  55    :  
  56    :        file_header_start.set_value(nt_header_pos +
  57  E :                                    offsetof(IMAGE_NT_HEADERS, FileHeader));
  58    :      }
  59    :  
  60  E :      bool success = ReadCommonHeaders(file, file_header_start);
  61  E :      if (success)
  62  E :        success = ReadSections(file);
  63    :  
  64  E :      base::CloseFile(file);
  65    :  
  66  E :      return success;
  67  E :    }
  68    :  };
  69    :  
  70    :  template <typename AddressType, size_t shift_base, size_t header_base>
  71    :  struct ShiftedAddressSpaceTraits {
  72    :    typedef typename AddressType AddressType;
  73    :    typedef unsigned int SizeType;
  74    :  
  75    :    static const size_t kShiftBase = shift_base;
  76    :  
  77  E :    static const AddressType invalid_address() {
  78  E :      return AddressType::kInvalidAddress;
  79  E :    }
  80    :  
  81  E :    static const AddressType header_address() {
  82  E :      return AddressType(header_base);
  83  E :    }
  84    :  
  85  E :    static AddressType GetSectionAddress(const IMAGE_SECTION_HEADER& header) {
  86    :      // VirtualAddress is not necessarily 0 for object files, but it
  87    :      // should, and MSVC should produce 0; we use that info as
  88    :      // a heuristic to decide on the address.
  89  E :      if (header.VirtualAddress == 0) {
  90    :        if ((header.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 &&
  91  E :            header.PointerToRawData == 0) {
  92    :          // Unmapped section.
  93  E :          return invalid_address();
  94  i :        } else {
  95  E :          return AddressType(kShiftBase + header.PointerToRawData);
  96    :        }
  97  i :      } else {
  98  E :        return AddressType(kShiftBase + header.VirtualAddress);
  99    :      }
 100  E :    }
 101    :  
 102  E :    static SizeType GetSectionSize(const IMAGE_SECTION_HEADER& header) {
 103  E :      return 1;
 104  E :    }
 105    :  };
 106    :  
 107    :  typedef ShiftedAddressSpaceTraits<AbsoluteAddress, 0x10000, 0x4>
 108    :      ShiftedVirtualAddressTraits;
 109    :  typedef ShiftedAddressSpaceTraits<FileOffsetAddress, 0x100, 0x100>
 110    :      ShiftedFileOffsetAddressTraits;
 111    :  
 112    :  class PECoffFileTest : public testing::PELibUnitTest {
 113    :    typedef testing::PELibUnitTest Super;
 114    :  
 115    :   public:
 116  E :    PECoffFileTest() {
 117  E :    }
 118    :  
 119  E :    virtual void SetUp() OVERRIDE {
 120  E :      Super::SetUp();
 121    :  
 122  E :      test_dll_path_ = testing::GetExeRelativePath(testing::kTestDllName);
 123    :      test_dll_coff_obj_path_ =
 124  E :          testing::GetExeTestDataRelativePath(testing::kTestDllCoffObjName);
 125    :      test_dll_ltcg_obj_path_ =
 126  E :          testing::GetExeTestDataRelativePath(testing::kTestDllLtcgObjName);
 127  E :    }
 128    :  
 129    :   protected:
 130  E :    bool InitImages() {
 131    :      return pe_image_file_.Init(test_dll_path_, true) &&
 132  E :          coff_image_file_.Init(test_dll_coff_obj_path_, false);
 133  E :    }
 134    :  
 135    :    base::FilePath test_dll_path_;
 136    :    base::FilePath test_dll_coff_obj_path_;
 137    :    base::FilePath test_dll_ltcg_obj_path_;
 138    :  
 139    :    TestPECoffFile<ShiftedVirtualAddressTraits> pe_image_file_;
 140    :    TestPECoffFile<ShiftedFileOffsetAddressTraits> coff_image_file_;
 141    :  
 142    :   private:
 143    :    DISALLOW_COPY_AND_ASSIGN(PECoffFileTest);
 144    :  };
 145    :  
 146    :  bool IsCoffSectionMapped(
 147    :      const TestPECoffFile<ShiftedFileOffsetAddressTraits>& image_file,
 148  E :      size_t i) {
 149  E :    const IMAGE_SECTION_HEADER* hdr = image_file.section_header(i);
 150    :    return hdr != NULL &&
 151    :        (ShiftedFileOffsetAddressTraits::GetSectionAddress(*hdr) !=
 152  E :         ShiftedFileOffsetAddressTraits::invalid_address());
 153  E :  }
 154    :  
 155    :  }  // namespace
 156    :  
 157  E :  TEST_F(PECoffFileTest, Init) {
 158  E :    EXPECT_TRUE(pe_image_file_.file_header() == NULL);
 159  E :    EXPECT_TRUE(pe_image_file_.section_headers() == NULL);
 160  E :    EXPECT_TRUE(coff_image_file_.file_header() == NULL);
 161  E :    EXPECT_TRUE(coff_image_file_.section_headers() == NULL);
 162    :  
 163  E :    ASSERT_TRUE(pe_image_file_.Init(test_dll_path_, true));
 164  E :    ASSERT_TRUE(coff_image_file_.Init(test_dll_coff_obj_path_, false));
 165    :  
 166  E :    EXPECT_TRUE(pe_image_file_.file_header() != NULL);
 167  E :    EXPECT_TRUE(pe_image_file_.section_headers() != NULL);
 168  E :    EXPECT_TRUE(coff_image_file_.file_header() != NULL);
 169  E :    EXPECT_TRUE(coff_image_file_.section_headers() != NULL);
 170    :  
 171  E :    EXPECT_EQ(pe_image_file_.file_header()->Machine, IMAGE_FILE_MACHINE_I386);
 172  E :    EXPECT_EQ(coff_image_file_.file_header()->Machine, IMAGE_FILE_MACHINE_I386);
 173    :  
 174  E :    EXPECT_TRUE(pe_image_file_.file_header()->SizeOfOptionalHeader != 0);
 175  E :    EXPECT_TRUE(coff_image_file_.file_header()->PointerToSymbolTable != 0);
 176  E :  }
 177    :  
 178  E :  TEST_F(PECoffFileTest, FailOnAnonymousObject) {
 179  E :    ASSERT_FALSE(coff_image_file_.Init(test_dll_ltcg_obj_path_, false));
 180  E :  }
 181    :  
 182    :  // Compare header data obtained from different methods.
 183  E :  TEST_F(PECoffFileTest, ReadFileHeader) {
 184  E :    ASSERT_TRUE(InitImages());
 185  E :    ASSERT_TRUE(coff_image_file_.file_header() != NULL);
 186    :  
 187  E :    IMAGE_FILE_HEADER header = {};
 188    :    ASSERT_TRUE(coff_image_file_.ReadImage(coff_image_file_.header_address(),
 189  E :                                           &header, sizeof(header)));
 190    :    EXPECT_TRUE(memcmp(static_cast<void*>(&header),
 191    :                       static_cast<const void*>(coff_image_file_.file_header()),
 192  E :                       sizeof(header)) == 0);
 193    :    uint8* ptr = coff_image_file_.GetImageData(coff_image_file_.header_address(),
 194  E :                                               sizeof(header));
 195  E :    ASSERT_TRUE(ptr != NULL);
 196    :    EXPECT_TRUE(memcmp(static_cast<void*>(&header),
 197    :                       static_cast<void*>(ptr),
 198  E :                       sizeof(header)) == 0);
 199  E :  }
 200    :  
 201  E :  TEST_F(PECoffFileTest, Contains) {
 202  E :    ASSERT_TRUE(InitImages());
 203  E :    EXPECT_TRUE(pe_image_file_.Contains(pe_image_file_.header_address(), 1));
 204  E :    EXPECT_FALSE(pe_image_file_.Contains(pe_image_file_.header_address() - 1, 1));
 205    :  
 206    :    // Should be a gap in the address space before the big shift of
 207    :    // ShiftedVirtualAddressTraits::kShiftBase.
 208    :    EXPECT_FALSE(pe_image_file_.Contains(
 209  E :        AbsoluteAddress(ShiftedVirtualAddressTraits::kShiftBase - 1), 1));
 210    :  
 211  E :    EXPECT_TRUE(coff_image_file_.Contains(coff_image_file_.header_address(), 1));
 212    :    EXPECT_FALSE(coff_image_file_.Contains(
 213  E :        coff_image_file_.header_address() - 1, 1));
 214  E :  }
 215    :  
 216  E :  TEST_F(PECoffFileTest, GetSectionIndex) {
 217  E :    ASSERT_TRUE(InitImages());
 218    :  
 219  E :    size_t num_sections = pe_image_file_.file_header()->NumberOfSections;
 220  E :    for (size_t i = 0; i < num_sections; ++i) {
 221    :      AbsoluteAddress section_start(
 222    :          ShiftedVirtualAddressTraits::GetSectionAddress(
 223  E :              *pe_image_file_.section_header(i)));
 224  E :      EXPECT_EQ(i, pe_image_file_.GetSectionIndex(section_start, 1));
 225  E :    }
 226    :  
 227  E :    AbsoluteAddress off_by_one(ShiftedVirtualAddressTraits::kShiftBase - 1);
 228  E :    EXPECT_EQ(kInvalidSection, pe_image_file_.GetSectionIndex(off_by_one, 1));
 229    :  
 230  E :    num_sections = coff_image_file_.file_header()->NumberOfSections;
 231  E :    for (size_t i = 0; i < num_sections; ++i) {
 232  E :      if (IsCoffSectionMapped(coff_image_file_, i)) {
 233    :        FileOffsetAddress section_start(
 234    :            ShiftedFileOffsetAddressTraits::GetSectionAddress(
 235  E :                *coff_image_file_.section_header(i)));
 236  E :        EXPECT_EQ(i, coff_image_file_.GetSectionIndex(section_start, 1));
 237    :      }
 238  E :    }
 239  E :  }
 240    :  
 241  E :  TEST_F(PECoffFileTest, GetSectionHeader) {
 242  E :    ASSERT_TRUE(InitImages());
 243    :  
 244  E :    size_t num_sections = pe_image_file_.file_header()->NumberOfSections;
 245  E :    for (size_t i = 0; i < num_sections; ++i) {
 246    :      AbsoluteAddress section_start(
 247    :          ShiftedVirtualAddressTraits::GetSectionAddress(
 248  E :              *pe_image_file_.section_header(i)));
 249    :      EXPECT_EQ(pe_image_file_.section_header(i),
 250  E :                pe_image_file_.GetSectionHeader(section_start, 1));
 251  E :    }
 252    :  
 253  E :    num_sections = coff_image_file_.file_header()->NumberOfSections;
 254  E :    for (size_t i = 0; i < num_sections; ++i) {
 255  E :      if (IsCoffSectionMapped(coff_image_file_, i)) {
 256    :        FileOffsetAddress section_start(
 257    :            ShiftedFileOffsetAddressTraits::GetSectionAddress(
 258  E :                *coff_image_file_.section_header(i)));
 259    :        EXPECT_EQ(coff_image_file_.section_header(i),
 260  E :                  coff_image_file_.GetSectionHeader(section_start, 1));
 261    :      }
 262  E :    }
 263  E :  }
 264    :  
 265  E :  TEST_F(PECoffFileTest, GetImageData) {
 266  E :    ASSERT_TRUE(InitImages());
 267  E :    ASSERT_TRUE(pe_image_file_.file_header() != NULL);
 268  E :    ASSERT_TRUE(coff_image_file_.file_header() != NULL);
 269    :  
 270  E :    size_t num_sections = pe_image_file_.file_header()->NumberOfSections;
 271  E :    for (size_t i = 0; i < num_sections; ++i) {
 272    :      AbsoluteAddress section_start(
 273    :          ShiftedVirtualAddressTraits::GetSectionAddress(
 274  E :              *pe_image_file_.section_header(i)));
 275  E :      EXPECT_TRUE(pe_image_file_.GetImageData(section_start, 1) != NULL);
 276  E :    }
 277    :  
 278  E :    num_sections = coff_image_file_.file_header()->NumberOfSections;
 279  E :    for (size_t i = 0; i < num_sections; ++i) {
 280  E :      if (IsCoffSectionMapped(coff_image_file_, i)) {
 281    :        FileOffsetAddress section_start(
 282    :            ShiftedFileOffsetAddressTraits::GetSectionAddress(
 283  E :                *coff_image_file_.section_header(i)));
 284  E :        EXPECT_TRUE(coff_image_file_.GetImageData(section_start, 1) != NULL);
 285    :      }
 286  E :    }
 287  E :  }
 288    :  
 289    :  }  // namespace pe

Coverage information generated Thu Mar 26 16:15:41 2015.