// Copyright (c) 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. // This file contains unit tests for PEImage. #include #include #include "base/files/file_path.h" #include "base/path_service.h" #include "base/win/pe_image.h" #include "testing/gtest/include/gtest/gtest.h" namespace base { namespace win { namespace { // Just counts the number of invocations. bool ImportsCallback(const PEImage& image, LPCSTR module, DWORD ordinal, LPCSTR name, DWORD hint, PIMAGE_THUNK_DATA iat, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } // Just counts the number of invocations. bool SectionsCallback(const PEImage& image, PIMAGE_SECTION_HEADER header, PVOID section_start, DWORD section_size, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } // Just counts the number of invocations. bool RelocsCallback(const PEImage& image, WORD type, PVOID address, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } // Just counts the number of invocations. bool ImportChunksCallback(const PEImage& image, LPCSTR module, PIMAGE_THUNK_DATA name_table, PIMAGE_THUNK_DATA iat, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } // Just counts the number of invocations. bool DelayImportChunksCallback(const PEImage& image, PImgDelayDescr delay_descriptor, LPCSTR module, PIMAGE_THUNK_DATA name_table, PIMAGE_THUNK_DATA iat, PIMAGE_THUNK_DATA bound_iat, PIMAGE_THUNK_DATA unload_iat, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } // Just counts the number of invocations. bool ExportsCallback(const PEImage& image, DWORD ordinal, DWORD hint, LPCSTR name, PVOID function, LPCSTR forward, PVOID cookie) { int* count = reinterpret_cast(cookie); (*count)++; return true; } } // namespace // Tests that we are able to enumerate stuff from a PE file, and that // the actual number of items found matches an expected value. TEST(PEImageTest, EnumeratesPE) { base::FilePath pe_image_test_path; ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &pe_image_test_path)); pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image")); #if defined(ARCH_CPU_64_BITS) pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_64.dll")); const int sections = 6; const int imports_dlls = 2; const int delay_dlls = 2; const int exports = 2; const int imports = 69; const int delay_imports = 2; const int relocs = 632; #else pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_32.dll")); const int sections = 5; const int imports_dlls = 2; const int delay_dlls = 2; const int exports = 2; const int imports = 66; const int delay_imports = 2; const int relocs = 1586; #endif HMODULE module = LoadLibrary(pe_image_test_path.value().c_str()); ASSERT_TRUE(NULL != module); PEImage pe(module); int count = 0; EXPECT_TRUE(pe.VerifyMagic()); pe.EnumSections(SectionsCallback, &count); EXPECT_EQ(sections, count); count = 0; pe.EnumImportChunks(ImportChunksCallback, &count); EXPECT_EQ(imports_dlls, count); count = 0; pe.EnumDelayImportChunks(DelayImportChunksCallback, &count); EXPECT_EQ(delay_dlls, count); count = 0; pe.EnumExports(ExportsCallback, &count); EXPECT_EQ(exports, count); count = 0; pe.EnumAllImports(ImportsCallback, &count); EXPECT_EQ(imports, count); count = 0; pe.EnumAllDelayImports(ImportsCallback, &count); EXPECT_EQ(delay_imports, count); count = 0; pe.EnumRelocs(RelocsCallback, &count); EXPECT_EQ(relocs, count); FreeLibrary(module); } // Tests that we can locate an specific exported symbol, by name and by ordinal. TEST(PEImageTest, RetrievesExports) { HMODULE module = LoadLibrary(L"advapi32.dll"); ASSERT_TRUE(NULL != module); PEImage pe(module); WORD ordinal; EXPECT_TRUE(pe.GetProcOrdinal("RegEnumKeyExW", &ordinal)); FARPROC address1 = pe.GetProcAddress("RegEnumKeyExW"); FARPROC address2 = pe.GetProcAddress(reinterpret_cast(ordinal)); EXPECT_TRUE(address1 != NULL); EXPECT_TRUE(address2 != NULL); EXPECT_TRUE(address1 == address2); FreeLibrary(module); } // Test that we can get debug id out of a module. TEST(PEImageTest, GetDebugId) { HMODULE module = LoadLibrary(L"advapi32.dll"); ASSERT_TRUE(NULL != module); PEImage pe(module); GUID guid = {0}; DWORD age = 0; EXPECT_TRUE(pe.GetDebugId(&guid, &age)); GUID empty_guid = {0}; EXPECT_TRUE(!IsEqualGUID(empty_guid, guid)); EXPECT_NE(0U, age); FreeLibrary(module); } } // namespace win } // namespace base