blob: 31c99a5d39039ee6d763ec370c24cef52ca7a2a9 [file] [log] [blame]
// Copyright 2008, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// This file contains unit tests for PEImage.
#include "testing/gtest/include/gtest/gtest.h"
#include "base/pe_image.h"
// 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<int*>(cookie);
(*count)++;
return true;
}
// 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<int*>(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<int*>(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<int*>(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<int*>(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<int*>(cookie);
(*count)++;
return true;
}
// We'll be using some known values for the tests.
enum Value {
sections = 0,
imports_dlls,
delay_dlls,
exports,
imports,
delay_imports,
relocs
};
// Retrieves the expected value from advapi32.dll based on the OS.
int GetExpectedValue(Value value, DWORD os) {
const int xp_delay_dlls = 2;
const int xp_exports = 675;
const int xp_imports = 422;
const int xp_delay_imports = 8;
const int xp_relocs = 9180;
const int vista_delay_dlls = 4;
const int vista_exports = 799;
const int vista_imports = 476;
const int vista_delay_imports = 24;
const int vista_relocs = 10188;
const int w2k_delay_dlls = 0;
const int w2k_exports = 566;
const int w2k_imports = 357;
const int w2k_delay_imports = 0;
const int w2k_relocs = 7388;
// Contains the expected value, for each enumerated property (Value), and the
// OS version: [Value][os_version]
const int expected[][3] = {
{4, 4, 4},
{3, 3, 3},
{w2k_delay_dlls, xp_delay_dlls, vista_delay_dlls},
{w2k_exports, xp_exports, vista_exports},
{w2k_imports, xp_imports, vista_imports},
{w2k_delay_imports, xp_delay_imports, vista_delay_imports},
{w2k_relocs, xp_relocs, vista_relocs}
};
if (value > relocs)
return 0;
if (50 == os)
os = 0; // 5.0
else if (51 == os || 52 == os)
os = 1;
else if (os >= 60)
os = 2; // 6.x
else
return 0;
return expected[value][os];
}
// Tests that we are able to enumerate stuff from a PE file, and that
// the actual number of items found is within the expected range.
TEST(PEImageTest, EnumeratesPE) {
HMODULE module = LoadLibrary(L"advapi32.dll");
ASSERT_TRUE(NULL != module);
PEImage pe(module);
int count = 0;
EXPECT_TRUE(pe.VerifyMagic());
DWORD os = pe.GetNTHeaders()->OptionalHeader.MajorOperatingSystemVersion;
os = os * 10 + pe.GetNTHeaders()->OptionalHeader.MinorOperatingSystemVersion;
pe.EnumSections(SectionsCallback, &count);
EXPECT_EQ(GetExpectedValue(sections, os), count);
count = 0;
pe.EnumImportChunks(ImportChunksCallback, &count);
EXPECT_EQ(GetExpectedValue(imports_dlls, os), count);
count = 0;
pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
EXPECT_EQ(GetExpectedValue(delay_dlls, os), count);
count = 0;
pe.EnumExports(ExportsCallback, &count);
EXPECT_GT(count, GetExpectedValue(exports, os) - 20);
EXPECT_LT(count, GetExpectedValue(exports, os) + 100);
count = 0;
pe.EnumAllImports(ImportsCallback, &count);
EXPECT_GT(count, GetExpectedValue(imports, os) - 20);
EXPECT_LT(count, GetExpectedValue(imports, os) + 100);
count = 0;
pe.EnumAllDelayImports(ImportsCallback, &count);
EXPECT_GT(count, GetExpectedValue(delay_imports, os) - 2);
EXPECT_LT(count, GetExpectedValue(delay_imports, os) + 8);
count = 0;
pe.EnumRelocs(RelocsCallback, &count);
EXPECT_GT(count, GetExpectedValue(relocs, os) - 150);
EXPECT_LT(count, GetExpectedValue(relocs, os) + 1500);
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<char*>(ordinal));
EXPECT_TRUE(address1 != NULL);
EXPECT_TRUE(address2 != NULL);
EXPECT_TRUE(address1 == address2);
FreeLibrary(module);
}