crashpad/snapshot/win/pe_image_reader_test.cc
Jan Wilken Dörrie a98ee20e57 [crashpad] Prepare crashpad for base::string16 switch
This change prepares crashpad for the upcoming switch of base::string16
to std::u16string on all platforms. It does so by replacing Windows-only
instances of base::string16 with std::wstring, and using appropriate
string utility functions.

Bug: chromium:911896
Change-Id: Ibb0b8a4e4dc7fae1d24d18823f8dbb6da31f8239
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/2332402
Commit-Queue: Jan Wilken Dörrie <jdoerrie@chromium.org>
Reviewed-by: Mark Mentovai <mark@chromium.org>
2020-09-12 07:36:53 +00:00

194 lines
7.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// Copyright 2015 The Crashpad Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "snapshot/win/pe_image_reader.h"
#ifndef PSAPI_VERSION
#define PSAPI_VERSION 2
#endif
#include <psapi.h>
#include "base/files/file_path.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "gtest/gtest.h"
#include "snapshot/win/process_reader_win.h"
#include "test/errors.h"
#include "test/scoped_module_handle.h"
#include "test/test_paths.h"
#include "util/misc/from_pointer_cast.h"
#include "util/win/get_module_information.h"
#include "util/win/module_version.h"
#include "util/win/process_info.h"
namespace crashpad {
namespace test {
namespace {
TEST(PEImageReader, DebugDirectory) {
base::FilePath module_path =
TestPaths::BuildArtifact(L"snapshot",
L"image_reader_module",
TestPaths::FileType::kLoadableModule);
ScopedModuleHandle module_handle(LoadLibrary(module_path.value().c_str()));
ASSERT_TRUE(module_handle.valid()) << ErrorMessage("LoadLibrary");
PEImageReader pe_image_reader;
ProcessReaderWin process_reader;
ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
ProcessSuspensionState::kRunning));
MODULEINFO module_info;
ASSERT_TRUE(CrashpadGetModuleInformation(GetCurrentProcess(),
module_handle.get(),
&module_info,
sizeof(module_info)))
<< ErrorMessage("GetModuleInformation");
EXPECT_EQ(module_info.lpBaseOfDll, module_handle.get());
base::FilePath module_basename = module_path.BaseName();
ASSERT_TRUE(pe_image_reader.Initialize(
&process_reader,
FromPointerCast<WinVMAddress>(module_handle.get()),
module_info.SizeOfImage,
base::WideToUTF8(module_basename.value())));
UUID uuid;
DWORD age;
std::string pdbname;
ASSERT_TRUE(pe_image_reader.DebugDirectoryInformation(&uuid, &age, &pdbname));
std::string module_name =
base::WideToUTF8(module_basename.RemoveFinalExtension().value());
EXPECT_NE(pdbname.find(module_name), std::string::npos);
const std::string suffix(".pdb");
EXPECT_EQ(
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix),
0);
}
void TestVSFixedFileInfo(ProcessReaderWin* process_reader,
const ProcessInfo::Module& module,
bool known_dll) {
PEImageReader pe_image_reader;
ASSERT_TRUE(pe_image_reader.Initialize(process_reader,
module.dll_base,
module.size,
base::WideToUTF8(module.name)));
VS_FIXEDFILEINFO observed;
const bool observed_rv = pe_image_reader.VSFixedFileInfo(&observed);
ASSERT_TRUE(observed_rv || !known_dll);
if (observed_rv) {
EXPECT_EQ(observed.dwSignature, static_cast<DWORD>(VS_FFI_SIGNATURE));
EXPECT_EQ(observed.dwStrucVersion, static_cast<DWORD>(VS_FFI_STRUCVERSION));
EXPECT_EQ(observed.dwFileFlags & ~observed.dwFileFlagsMask, 0u);
if (known_dll) {
EXPECT_EQ(observed.dwFileOS, static_cast<DWORD>(VOS_NT_WINDOWS32));
EXPECT_EQ(observed.dwFileType, static_cast<DWORD>(VFT_DLL));
} else {
EXPECT_NE(observed.dwFileOS & VOS_NT_WINDOWS32, 0u);
// VFT_DRV/VFT2_DRV_NETWORK is for nsi.dll, “network service interface.”
// Its not normally loaded, but has been observed to be loaded in some
// cases.
EXPECT_TRUE(observed.dwFileType == VFT_APP ||
observed.dwFileType == VFT_DLL ||
(observed.dwFileType == VFT_DRV &&
observed.dwFileSubtype == VFT2_DRV_NETWORK))
<< base::StringPrintf("type 0x%lx, subtype 0x%lx",
observed.dwFileType,
observed.dwFileSubtype);
}
}
base::FilePath module_path(module.name);
const DWORD version = GetVersion();
const int major_version = LOBYTE(LOWORD(version));
const int minor_version = HIBYTE(LOWORD(version));
if (major_version > 6 || (major_version == 6 && minor_version >= 2)) {
// Windows 8 or later.
//
// Use BaseName() to ensure that GetModuleVersionAndType() finds the
// already-loaded module with the specified name. Otherwise, dwFileVersionMS
// may not match. This appears to be related to the changes made in Windows
// 8.1 to GetVersion() and GetVersionEx() for non-manifested applications
module_path = module_path.BaseName();
}
VS_FIXEDFILEINFO expected;
const bool expected_rv = GetModuleVersionAndType(module_path, &expected);
ASSERT_TRUE(expected_rv || !known_dll);
EXPECT_EQ(observed_rv, expected_rv);
if (observed_rv && expected_rv) {
EXPECT_EQ(observed.dwSignature, expected.dwSignature);
EXPECT_EQ(observed.dwStrucVersion, expected.dwStrucVersion);
EXPECT_EQ(observed.dwFileVersionMS, expected.dwFileVersionMS);
EXPECT_EQ(observed.dwFileVersionLS, expected.dwFileVersionLS);
EXPECT_EQ(observed.dwProductVersionMS, expected.dwProductVersionMS);
EXPECT_EQ(observed.dwProductVersionLS, expected.dwProductVersionLS);
EXPECT_EQ(observed.dwFileFlagsMask, expected.dwFileFlagsMask);
EXPECT_EQ(observed.dwFileFlags, expected.dwFileFlags);
EXPECT_EQ(observed.dwFileOS, expected.dwFileOS);
EXPECT_EQ(observed.dwFileType, expected.dwFileType);
EXPECT_EQ(observed.dwFileSubtype, expected.dwFileSubtype);
EXPECT_EQ(observed.dwFileDateMS, expected.dwFileDateMS);
EXPECT_EQ(observed.dwFileDateLS, expected.dwFileDateLS);
}
}
TEST(PEImageReader, VSFixedFileInfo_OneModule) {
ProcessReaderWin process_reader;
ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
ProcessSuspensionState::kRunning));
static constexpr wchar_t kModuleName[] = L"kernel32.dll";
const HMODULE module_handle = GetModuleHandle(kModuleName);
ASSERT_TRUE(module_handle) << ErrorMessage("GetModuleHandle");
MODULEINFO module_info;
ASSERT_TRUE(CrashpadGetModuleInformation(
GetCurrentProcess(), module_handle, &module_info, sizeof(module_info)))
<< ErrorMessage("GetModuleInformation");
EXPECT_EQ(module_info.lpBaseOfDll, module_handle);
ProcessInfo::Module module;
module.name = kModuleName;
module.dll_base = FromPointerCast<WinVMAddress>(module_info.lpBaseOfDll);
module.size = module_info.SizeOfImage;
TestVSFixedFileInfo(&process_reader, module, true);
}
TEST(PEImageReader, VSFixedFileInfo_AllModules) {
ProcessReaderWin process_reader;
ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
ProcessSuspensionState::kRunning));
const std::vector<ProcessInfo::Module>& modules = process_reader.Modules();
EXPECT_GT(modules.size(), 2u);
for (const auto& module : modules) {
SCOPED_TRACE(base::WideToUTF8(module.name));
TestVSFixedFileInfo(&process_reader, module, false);
}
}
} // namespace
} // namespace test
} // namespace crashpad