Coverage for /Syzygy/pe/pe_file_unittest.cc

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
98.6%2842880.C++test

Line-by-line coverage:

   1    :  // Copyright 2012 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_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    :  using core::SectionOffsetAddress;
  34    :  
  35    :  class PEFileTest: public testing::PELibUnitTest {
  36    :    typedef testing::PELibUnitTest Super;
  37    :  
  38    :   public:
  39  E :    PEFileTest() : test_dll_(NULL) {
  40  E :    }
  41    :  
  42  E :    virtual void SetUp() override {
  43  E :      Super::SetUp();
  44    :  
  45    :      base::FilePath test_dll =
  46  E :          testing::GetExeRelativePath(testing::kTestDllName);
  47  E :      base::NativeLibraryLoadError error;
  48  E :      test_dll_ = base::LoadNativeLibrary(test_dll, &error);
  49    :  
  50  E :      ASSERT_TRUE(image_file_.Init(test_dll));
  51    :  
  52    :      base::FilePath test_dll_64 =
  53  E :          testing::GetExeRelativePath(testing::kTestDllName64);
  54  E :      test_dll_64_ = base::LoadNativeLibrary(test_dll_64, &error);
  55    :  
  56  E :      ASSERT_TRUE(image_file_64_.Init(test_dll_64));
  57  E :    }
  58    :  
  59  E :    virtual void TearDown() override {
  60  E :      base::UnloadNativeLibrary(test_dll_);
  61  E :      base::UnloadNativeLibrary(test_dll_64_);
  62  E :      Super::TearDown();
  63  E :    }
  64    :  
  65    :    void TestAddressesAreConsistent(RelativeAddress rel,
  66    :                                    AbsoluteAddress abs,
  67    :                                    FileOffsetAddress off,
  68  E :                                    SectionOffsetAddress sect_off) {
  69  E :      AbsoluteAddress abs2;
  70  E :      RelativeAddress rel2;
  71  E :      FileOffsetAddress off2;
  72  E :      SectionOffsetAddress sect_off2;
  73    :  
  74  E :      ASSERT_TRUE(image_file_.Translate(rel, &abs2));
  75  E :      ASSERT_EQ(abs, abs2);
  76    :  
  77  E :      ASSERT_TRUE(image_file_.Translate(abs, &rel2));
  78  E :      ASSERT_EQ(rel, rel2);
  79    :  
  80  E :      ASSERT_TRUE(image_file_.Translate(off, &rel2));
  81  E :      ASSERT_EQ(rel, rel2);
  82    :  
  83  E :      ASSERT_TRUE(image_file_.Translate(rel, &off2));
  84  E :      ASSERT_EQ(off, off2);
  85    :  
  86  E :      ASSERT_TRUE(image_file_.Translate(rel, &sect_off2));
  87  E :      ASSERT_EQ(sect_off, sect_off2);
  88  E :    }
  89    :  
  90    :   protected:
  91    :    pe::PEFile image_file_;
  92    :    pe::PEFile64 image_file_64_;
  93    :    base::NativeLibrary test_dll_;
  94    :    base::NativeLibrary test_dll_64_;
  95    :  };
  96    :  
  97    :  // Functor for comparing import infos.
  98    :  struct CompareImportInfo {
  99    :    bool operator()(const PEFile::ImportInfo& ii1,
 100  E :                    const PEFile::ImportInfo& ii2) {
 101  E :      if (ii1.hint < ii2.hint)
 102  E :        return true;
 103  E :      if (ii1.hint > ii2.hint)
 104  i :        return false;
 105  E :      if (ii1.ordinal < ii2.ordinal)
 106  E :        return true;
 107  i :      if (ii1.ordinal > ii2.ordinal)
 108  i :        return false;
 109  i :      return ii1.function < ii2.function;
 110  E :    }
 111    :  };
 112    :  
 113    :  }  // namespace
 114    :  
 115  E :  TEST_F(PEFileTest, Create) {
 116  E :    PEFile image_file;
 117    :  
 118  E :    ASSERT_EQ(NULL, image_file.dos_header());
 119  E :    ASSERT_EQ(NULL, image_file.nt_headers());
 120  E :    ASSERT_EQ(NULL, image_file.section_headers());
 121  E :  }
 122    :  
 123  E :  TEST_F(PEFileTest, Init) {
 124  E :    EXPECT_TRUE(image_file_.dos_header() != NULL);
 125  E :    EXPECT_TRUE(image_file_.nt_headers() != NULL);
 126  E :    EXPECT_TRUE(image_file_.section_headers() != NULL);
 127  E :  }
 128    :  
 129  E :  TEST_F(PEFileTest, GetImageData) {
 130  E :    const IMAGE_NT_HEADERS* nt_headers = image_file_.nt_headers();
 131  E :    ASSERT_TRUE(nt_headers != NULL);
 132    :    const IMAGE_DATA_DIRECTORY* exports =
 133  E :        &nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
 134    :  
 135    :    // We should be able to read the export directory.
 136    :    ASSERT_TRUE(image_file_.GetImageData(RelativeAddress(exports->VirtualAddress),
 137  E :                                        exports->Size) != NULL);
 138    :  
 139    :    // We should be able to read it using an absolute address as well.
 140  E :    AbsoluteAddress abs_addr;
 141    :    ASSERT_TRUE(image_file_.Translate(RelativeAddress(exports->VirtualAddress),
 142  E :                                      &abs_addr));
 143  E :    ASSERT_TRUE(image_file_.GetImageData(abs_addr, exports->Size) != NULL);
 144    :  
 145    :    // But there ought to be a gap in the image data past the header size.
 146    :    ASSERT_TRUE(image_file_.GetImageData(
 147  E :        RelativeAddress(nt_headers->OptionalHeader.SizeOfHeaders), 1) == NULL);
 148  E :  }
 149    :  
 150  E :  TEST_F(PEFileTest, ReadImage) {
 151  E :    const IMAGE_NT_HEADERS* nt_headers = image_file_.nt_headers();
 152  E :    ASSERT_TRUE(nt_headers != NULL);
 153    :    const IMAGE_DATA_DIRECTORY* exports =
 154  E :        &nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
 155    :  
 156    :    // We should be able to read the export directory.
 157  E :    IMAGE_EXPORT_DIRECTORY export_dir = {};
 158    :    ASSERT_TRUE(image_file_.ReadImage(RelativeAddress(exports->VirtualAddress),
 159    :                                      &export_dir,
 160  E :                                      sizeof(export_dir)));
 161    :  
 162    :    // Check that we actually read something.
 163  E :    IMAGE_EXPORT_DIRECTORY zero_export_dir = {};
 164  E :    ASSERT_NE(0, memcmp(&export_dir, &zero_export_dir, sizeof(export_dir)));
 165    :  
 166    :    // Now test the ReadImageString function.
 167  E :    std::vector<RelativeAddress> names(export_dir.NumberOfNames);
 168    :    ASSERT_TRUE(image_file_.ReadImage(RelativeAddress(export_dir.AddressOfNames),
 169    :                                      &names.at(0),
 170  E :                                      sizeof(names[0]) * names.size()));
 171    :  
 172    :    // Test the same thing using an absolute address.
 173  E :    AbsoluteAddress abs_names_addr;
 174    :    ASSERT_TRUE(image_file_.Translate(RelativeAddress(export_dir.AddressOfNames),
 175  E :                                      &abs_names_addr));
 176  E :    std::vector<RelativeAddress> names2(export_dir.NumberOfNames);
 177    :    ASSERT_TRUE(image_file_.ReadImage(abs_names_addr, &names2.at(0),
 178  E :                                      sizeof(names2[0]) * names2.size()));
 179  E :    ASSERT_EQ(names, names2);
 180    :  
 181    :    // Read all the export name strings.
 182  E :    for (size_t i = 0; i < names.size(); ++i) {
 183  E :      std::string name1;
 184  E :      ASSERT_TRUE(image_file_.ReadImageString(names[i], &name1));
 185    :      ASSERT_TRUE(name1 == "function1" ||
 186    :                  name1 == "function3" ||
 187    :                  name1 == "DllMain" ||
 188    :                  name1 == "CreateFileW" ||
 189    :                  name1 == "TestUnusedFuncs" ||
 190    :                  name1 == "TestExport" ||
 191    :                  name1 == "LabelTestFunc" ||
 192    :                  name1 == "BringInOle32DelayLib" ||
 193    :                  name1 == "TestFunctionWithNoPrivateSymbols" ||
 194    :                  name1 == "FuncWithOffsetOutOfImage" ||
 195  E :                  name1 == "EndToEndTest");
 196    :  
 197  E :      std::string name2;
 198  E :      AbsoluteAddress abs_addr;
 199  E :      ASSERT_TRUE(image_file_.Translate(names[i], &abs_addr));
 200  E :      ASSERT_TRUE(image_file_.ReadImageString(abs_addr, &name2));
 201  E :      ASSERT_EQ(name1, name2);
 202  E :    }
 203  E :  }
 204    :  
 205  E :  TEST_F(PEFileTest, Contains) {
 206  E :    RelativeAddress relative_base(0);
 207  E :    AbsoluteAddress absolute_base;
 208  E :    size_t image_size = image_file_.nt_headers()->OptionalHeader.SizeOfImage;
 209  E :    RelativeAddress relative_end(image_size);
 210    :    AbsoluteAddress absolute_end(
 211  E :        image_file_.nt_headers()->OptionalHeader.ImageBase + image_size);
 212    :  
 213  E :    ASSERT_TRUE(image_file_.Translate(relative_base, &absolute_base));
 214  E :    ASSERT_TRUE(image_file_.Contains(relative_base, 1));
 215  E :    ASSERT_TRUE(image_file_.Contains(absolute_base, 1));
 216  E :    ASSERT_FALSE(image_file_.Contains(absolute_base - 1, 1));
 217  E :    ASSERT_FALSE(image_file_.Contains(absolute_end, 1));
 218  E :    ASSERT_FALSE(image_file_.Contains(relative_end, 1));
 219    :  
 220    :    // TODO(rogerm): test for inclusion at the end of the address space
 221    :    //    The way the address space is built only captures the ranges
 222    :    //    specified as sections in the headers, not the overall image size.
 223    :    //    Either the test needs to be more invasive or the data structure
 224    :    //    needs to be more broadly representative.  Note sure which, but
 225    :    //    it's not critical.
 226    :  
 227    :    // ASSERT_TRUE(image_file_.Contains(absolute_end - 1, 1));
 228  E :  }
 229    :  
 230  E :  TEST_F(PEFileTest, Translate) {
 231    :    // Try an address inside the headers (outside of any section).
 232  E :    AbsoluteAddress abs(image_file_.nt_headers()->OptionalHeader.ImageBase + 3);
 233  E :    RelativeAddress rel(3);
 234  E :    FileOffsetAddress off(3);
 235  E :    SectionOffsetAddress sect_off(0, 3);
 236  E :    ASSERT_NO_FATAL_FAILURE(TestAddressesAreConsistent(rel, abs, off, sect_off));
 237    :  
 238    :    // Now try an address in each of the sections.
 239  E :    size_t i = 0;
 240  E :    for (; i < image_file_.nt_headers()->FileHeader.NumberOfSections; ++i) {
 241  E :      const IMAGE_SECTION_HEADER* section = image_file_.section_header(i);
 242    :  
 243    :      AbsoluteAddress abs(section->VirtualAddress +
 244  E :          image_file_.nt_headers()->OptionalHeader.ImageBase + i);
 245  E :      RelativeAddress rel(section->VirtualAddress + i);
 246  E :      FileOffsetAddress off(section->PointerToRawData + i);
 247  E :      SectionOffsetAddress sect_off(i + 1, i);
 248    :  
 249    :      ASSERT_NO_FATAL_FAILURE(
 250  E :          TestAddressesAreConsistent(rel, abs, off, sect_off));
 251  E :    }
 252  E :  }
 253    :  
 254  E :  TEST_F(PEFileTest, TranslateOffImageFails) {
 255    :    const IMAGE_SECTION_HEADER* section = image_file_.section_header(
 256  E :        image_file_.nt_headers()->FileHeader.NumberOfSections - 1);
 257    :  
 258    :    AbsoluteAddress abs_end(image_file_.nt_headers()->OptionalHeader.ImageBase +
 259  E :        image_file_.nt_headers()->OptionalHeader.SizeOfImage);
 260  E :    RelativeAddress rel_end(image_file_.nt_headers()->OptionalHeader.SizeOfImage);
 261  E :    FileOffsetAddress off_end(section->PointerToRawData + section->SizeOfRawData);
 262    :  
 263  E :    AbsoluteAddress abs;
 264  E :    RelativeAddress rel;
 265  E :    FileOffsetAddress off;
 266  E :    ASSERT_FALSE(image_file_.Translate(rel_end, &abs));
 267  E :    ASSERT_FALSE(image_file_.Translate(abs_end, &rel));
 268  E :    ASSERT_FALSE(image_file_.Translate(off_end, &rel));
 269  E :    ASSERT_FALSE(image_file_.Translate(rel_end, &off));
 270  E :  }
 271    :  
 272  E :  TEST_F(PEFileTest, TranslateFileOffsetSpaceNotContiguous) {
 273  E :    size_t data_index = image_file_.GetSectionIndex(".data");
 274  E :    ASSERT_NE(kInvalidSection, data_index);
 275    :  
 276    :    const IMAGE_SECTION_HEADER* data =
 277  E :        image_file_.section_header(data_index);
 278  E :    ASSERT_TRUE(data != NULL);
 279    :  
 280  E :    RelativeAddress rel1, rel2;
 281  E :    rel1.set_value(data->VirtualAddress + data->SizeOfRawData - 1);
 282  E :    rel2.set_value(data->VirtualAddress + data->SizeOfRawData);
 283    :  
 284  E :    FileOffsetAddress off1, off2;
 285  E :    ASSERT_TRUE(image_file_.Translate(rel1, &off1));
 286  E :    ASSERT_FALSE(image_file_.Translate(rel2, &off2));
 287    :  
 288  E :    RelativeAddress rel3;
 289  E :    off2 = off1 + 1;
 290  E :    ASSERT_TRUE(image_file_.Translate(off2, &rel3));
 291  E :    ASSERT_LT(1, rel3 - rel2);
 292  E :  }
 293    :  
 294  E :  TEST_F(PEFileTest, DecodeRelocs) {
 295  E :    PEFile::RelocSet relocs;
 296  E :    ASSERT_TRUE(image_file_.DecodeRelocs(&relocs));
 297    :  
 298  E :    PEFile::RelocMap reloc_values;
 299  E :    ASSERT_TRUE(image_file_.ReadRelocs(relocs, &reloc_values));
 300    :  
 301    :    // We expect to have some relocs to validate and we expect that
 302    :    // all relocation table entries and their corresponding values
 303    :    // fall within the image's address space
 304  E :    ASSERT_TRUE(!reloc_values.empty());
 305  E :    PEFile::RelocMap::const_iterator i = reloc_values.begin();
 306  E :    for (; i != reloc_values.end(); ++i) {
 307    :      // Note:
 308    :      //  i->first is a relative pointer yielded by the relocation table
 309    :      //  i->second is the absolute value of that pointer (i.e., the relocation)
 310    :  
 311  E :      const RelativeAddress &pointer_location(i->first);
 312    :  
 313    :      ASSERT_TRUE(
 314  E :          image_file_.Contains(pointer_location, sizeof(AbsoluteAddress)));
 315  E :    }
 316  E :  }
 317    :  
 318  E :  TEST_F(PEFileTest, DecodeExports) {
 319  E :    PEFile::ExportInfoVector exports;
 320  E :    ASSERT_TRUE(image_file_.DecodeExports(&exports));
 321    :  
 322    :    // This must match the information in the test_dll.def file.
 323    :    PEFile::ExportInfo expected[] = {
 324    :      { RelativeAddress(0), "", "",  1 },
 325    :      { RelativeAddress(0), "BringInOle32DelayLib", "",  2 },
 326    :      { RelativeAddress(0), "TestExport", "", 3 },
 327    :      { RelativeAddress(0), "TestUnusedFuncs", "", 4 },
 328    :      { RelativeAddress(0), "LabelTestFunc", "", 5 },
 329    :      { RelativeAddress(0), "TestFunctionWithNoPrivateSymbols", "", 6 },
 330    :      { RelativeAddress(0), "DllMain", "", 7 },
 331    :      { RelativeAddress(0), "function3", "", 9 },
 332    :      { RelativeAddress(0), "CreateFileW", "kernel32.CreateFileW", 13 },
 333    :      { RelativeAddress(0), "function1", "", 17 },
 334    :      { RelativeAddress(0), "FuncWithOffsetOutOfImage", "", 18 },
 335  E :    };
 336    :  
 337  E :    ASSERT_EQ(ARRAYSIZE(expected), exports.size());
 338    :  
 339  E :    const uint8* module_base = reinterpret_cast<const uint8*>(test_dll_);
 340    :  
 341    :    // Resolve the exports and compare.
 342  E :    for (size_t i = 0; i < arraysize(expected); ++i) {
 343  E :      if (expected[i].forward.empty()) {
 344    :        // Look up the functions by ordinal.
 345    :        const uint8* function = reinterpret_cast<const uint8*>(
 346    :            base::GetFunctionPointerFromNativeLibrary(
 347  E :                test_dll_, reinterpret_cast<const char*>(expected[i].ordinal)));
 348  E :        EXPECT_TRUE(function != NULL);
 349    :  
 350  E :        expected[i].function = RelativeAddress(function - module_base);
 351    :      }
 352  E :      EXPECT_EQ(expected[i].function, exports.at(i).function);
 353  E :      EXPECT_EQ(expected[i].name, exports.at(i).name);
 354  E :      EXPECT_EQ(expected[i].forward, exports.at(i).forward);
 355  E :      EXPECT_EQ(expected[i].ordinal, exports.at(i).ordinal);
 356  E :    }
 357  E :  }
 358    :  
 359  E :  TEST_F(PEFileTest, DecodeImports) {
 360  E :    PEFile::ImportDllVector imports;
 361  E :    ASSERT_TRUE(image_file_.DecodeImports(&imports));
 362    :  
 363    :    // Validation the read imports section.
 364    :    // The test image imports at least kernel32 and the export_dll.
 365  E :    ASSERT_LE(2U, imports.size());
 366    :  
 367  E :    for (size_t i = 0; i < imports.size(); ++i) {
 368  E :      PEFile::ImportDll& dll = imports[i];
 369    :      if (0 ==
 370  E :          base::CompareCaseInsensitiveASCII("export_dll.dll", dll.name.c_str())) {
 371  E :        ASSERT_EQ(4, dll.functions.size());
 372    :        // Depending on the optimization settings the order of these elements can
 373    :        // actually be different.
 374    :        ASSERT_THAT(dll.functions, testing::WhenSortedBy(
 375    :            CompareImportInfo(),
 376    :            testing::ElementsAre(
 377    :                PEFile::ImportInfo(0, 0, "function1"),
 378    :                PEFile::ImportInfo(0, 7, ""),
 379    :                PEFile::ImportInfo(1, 0, "function3"),
 380  E :                PEFile::ImportInfo(2, 0, "kExportedData"))));
 381    :      }
 382  E :    }
 383  E :  }
 384    :  
 385  E :  TEST_F(PEFileTest, DecodeImportsX64) {
 386  E :    PEFile64::ImportDllVector imports;
 387  E :    ASSERT_TRUE(image_file_64_.DecodeImports(&imports));
 388    :  
 389    :    // Validate the read imports section.
 390    :    // The test image imports at least kernel32 and user32.
 391  E :    ASSERT_LE(2U, imports.size());
 392    :  
 393  E :    int expected_imports = 0;
 394  E :    for (size_t i = 0; i < imports.size(); ++i) {
 395  E :      PEFile64::ImportDll& dll = imports[i];
 396    :      if (base::CompareCaseInsensitiveASCII("kernel32.dll", dll.name.c_str()) ==
 397    :              0 ||
 398    :          base::CompareCaseInsensitiveASCII("user32.dll", dll.name.c_str()) ==
 399  E :              0) {
 400  E :        expected_imports++;
 401    :      }
 402  E :    }
 403    :  
 404  E :    EXPECT_EQ(2, expected_imports);
 405  E :  }
 406    :  
 407  E :  TEST_F(PEFileTest, GetSectionIndexByRelativeAddress) {
 408  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 409  E :    for (size_t i = 0; i < num_sections; ++i) {
 410    :      RelativeAddress section_start(
 411  E :          image_file_.section_header(i)->VirtualAddress);
 412  E :      EXPECT_EQ(i, image_file_.GetSectionIndex(section_start, 1));
 413  E :    }
 414    :  
 415    :    RelativeAddress off_end(image_file_.nt_headers()->OptionalHeader.SizeOfImage +
 416  E :        0x10000);
 417  E :    EXPECT_EQ(kInvalidSection, image_file_.GetSectionIndex(off_end, 1));
 418  E :  }
 419    :  
 420  E :  TEST_F(PEFileTest, GetSectionIndexByAbsoluteAddress) {
 421  E :    size_t image_base = image_file_.nt_headers()->OptionalHeader.ImageBase;
 422  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 423  E :    for (size_t i = 0; i < num_sections; ++i) {
 424    :      AbsoluteAddress section_start(
 425  E :          image_file_.section_header(i)->VirtualAddress + image_base);
 426  E :      EXPECT_EQ(i, image_file_.GetSectionIndex(section_start, 1));
 427  E :    }
 428    :  
 429    :    AbsoluteAddress off_end(image_file_.nt_headers()->OptionalHeader.SizeOfImage +
 430  E :        0x10000 + image_base);
 431  E :    EXPECT_EQ(kInvalidSection, image_file_.GetSectionIndex(off_end, 1));
 432  E :  }
 433    :  
 434  E :  TEST_F(PEFileTest, GetSectionIndexByName) {
 435  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 436  E :    for (size_t i = 0; i < num_sections; ++i) {
 437  E :      std::string name = image_file_.GetSectionName(i);
 438  E :      EXPECT_EQ(i, image_file_.GetSectionIndex(name.c_str()));
 439  E :    }
 440    :  
 441  E :    EXPECT_EQ(kInvalidSection, image_file_.GetSectionIndex(".foobar"));
 442  E :  }
 443    :  
 444  E :  TEST_F(PEFileTest, GetSectionHeaderByRelativeAddress) {
 445  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 446  E :    for (size_t i = 0; i < num_sections; ++i) {
 447    :      RelativeAddress section_start(
 448  E :          image_file_.section_header(i)->VirtualAddress);
 449    :      EXPECT_EQ(image_file_.section_header(i),
 450  E :                image_file_.GetSectionHeader(section_start, 1));
 451  E :    }
 452    :  
 453    :    RelativeAddress off_end(image_file_.nt_headers()->OptionalHeader.SizeOfImage +
 454  E :        0x10000);
 455  E :    EXPECT_EQ(kInvalidSection, image_file_.GetSectionIndex(off_end, 1));
 456  E :  }
 457    :  
 458  E :  TEST_F(PEFileTest, GetSectionHeaderByAbsoluteAddress) {
 459  E :    size_t image_base = image_file_.nt_headers()->OptionalHeader.ImageBase;
 460  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 461  E :    for (size_t i = 0; i < num_sections; ++i) {
 462    :      AbsoluteAddress section_start(
 463  E :          image_file_.section_header(i)->VirtualAddress + image_base);
 464    :      EXPECT_EQ(image_file_.section_header(i),
 465  E :                image_file_.GetSectionHeader(section_start, 1));
 466  E :    }
 467    :  
 468    :    AbsoluteAddress off_end(image_file_.nt_headers()->OptionalHeader.SizeOfImage +
 469  E :        0x10000 + image_base);
 470  E :    EXPECT_EQ(kInvalidSection, image_file_.GetSectionIndex(off_end, 1));
 471  E :  }
 472    :  
 473  E :  TEST_F(PEFileTest, GetSectionHeaderByName) {
 474  E :    size_t num_sections = image_file_.nt_headers()->FileHeader.NumberOfSections;
 475  E :    for (size_t i = 0; i < num_sections; ++i) {
 476  E :      std::string name = image_file_.GetSectionName(i);
 477    :      EXPECT_EQ(image_file_.section_header(i),
 478  E :                image_file_.GetSectionHeader(name.c_str()));
 479  E :    }
 480    :  
 481  E :    EXPECT_EQ(NULL, image_file_.GetSectionHeader(".foobar"));
 482  E :  }
 483    :  
 484  E :  TEST(PEFileSignatureTest, Serialization) {
 485  E :    PEFile::Signature sig;
 486  E :    sig.path = L"C:\foo\bar.dll";
 487  E :    sig.base_address = AbsoluteAddress(0x1000000);
 488  E :    sig.module_size = 12345;
 489  E :    sig.module_time_date_stamp = 9999999;
 490  E :    sig.module_checksum = 0xbaadf00d;
 491    :  
 492  E :    EXPECT_TRUE(testing::TestSerialization(sig));
 493  E :  }
 494    :  
 495  E :  TEST(PEFileSignatureTest, Consistency) {
 496  E :    PEFile::Signature sig1;
 497  E :    sig1.path = L"C:\\foo\\bar.dll";
 498  E :    sig1.base_address = AbsoluteAddress(0x1000000);
 499  E :    sig1.module_size = 12345;
 500  E :    sig1.module_time_date_stamp = 9999999;
 501  E :    sig1.module_checksum = 0xbaadf00d;
 502    :  
 503    :    // sig2 is the same, but with a different module path.
 504  E :    PEFile::Signature sig2(sig1);
 505  E :    sig2.path = L"C:\\foo\\bar.exe";
 506    :  
 507  E :    EXPECT_FALSE(sig1 == sig2);
 508  E :    EXPECT_TRUE(sig1.IsConsistent(sig2));
 509  E :    EXPECT_TRUE(sig1.IsConsistentExceptForChecksum(sig2));
 510    :  
 511  E :    sig2.module_checksum = sig1.module_checksum + 100;
 512  E :    EXPECT_FALSE(sig1.IsConsistent(sig2));
 513  E :    EXPECT_TRUE(sig1.IsConsistentExceptForChecksum(sig2));
 514  E :    sig2.module_checksum = sig1.module_checksum;
 515    :  
 516  E :    sig2.base_address = sig1.base_address + 0x1000;
 517  E :    EXPECT_FALSE(sig1.IsConsistent(sig2));
 518  E :    EXPECT_FALSE(sig1.IsConsistentExceptForChecksum(sig2));
 519  E :    sig2.base_address = sig1.base_address;
 520    :  
 521  E :    sig2.module_size = sig2.module_size + 0x1000;
 522  E :    EXPECT_FALSE(sig1.IsConsistent(sig2));
 523  E :    EXPECT_FALSE(sig1.IsConsistentExceptForChecksum(sig2));
 524  E :  }
 525    :  
 526    :  }  // namespace pe

Coverage information generated Thu Jan 14 17:40:38 2016.