Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(704)

Unified Diff: snapshot/win/pe_image_reader.cc

Issue 1475023004: Get module versions and types from in-memory images (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: snapshot/win/pe_image_reader.cc
diff --git a/snapshot/win/pe_image_reader.cc b/snapshot/win/pe_image_reader.cc
index 82bce0645ad57f82fcf6dc6f69b073660b20f9c1..2ebe7061f7322fbf6623b4200b48bb79600e46b2 100644
--- a/snapshot/win/pe_image_reader.cc
+++ b/snapshot/win/pe_image_reader.cc
@@ -18,8 +18,8 @@
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
-#include "base/strings/stringprintf.h"
#include "client/crashpad_info.h"
+#include "snapshot/win/pe_image_resource_reader.h"
#include "snapshot/win/process_reader_win.h"
#include "util/misc/pdb_structures.h"
#include "util/win/process_structs.h"
@@ -28,13 +28,6 @@ namespace crashpad {
namespace {
-std::string RangeToString(const CheckedWinAddressRange& range) {
- return base::StringPrintf("[0x%llx + 0x%llx (%s)]",
- range.Base(),
- range.Size(),
- range.Is64Bit() ? "64" : "32");
-}
-
// Map from Traits to an IMAGE_NT_HEADERSxx.
template <class Traits>
struct NtHeadersForTraits;
@@ -71,7 +64,7 @@ bool PEImageReader::Initialize(ProcessReaderWin* process_reader,
module_range_.SetRange(process_reader_->Is64Bit(), address, size);
if (!module_range_.IsValid()) {
LOG(WARNING) << "invalid module range for " << module_name << ": "
- << RangeToString(module_range_);
+ << module_range_.AsString();
return false;
}
module_name_ = module_name;
@@ -101,7 +94,7 @@ bool PEImageReader::GetCrashpadInfo(
section.Misc.VirtualSize);
if (!crashpad_info_range.IsValid()) {
LOG(WARNING) << "invalid range for crashpad info: "
- << RangeToString(crashpad_info_range);
+ << crashpad_info_range.AsString();
return false;
}
@@ -130,37 +123,10 @@ bool PEImageReader::GetCrashpadInfo(
bool PEImageReader::DebugDirectoryInformation(UUID* uuid,
DWORD* age,
std::string* pdbname) const {
- if (process_reader_->Is64Bit()) {
- return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS64>(
- uuid, age, pdbname);
- } else {
- return ReadDebugDirectoryInformation<IMAGE_NT_HEADERS32>(
- uuid, age, pdbname);
- }
-}
-
-template <class NtHeadersType>
-bool PEImageReader::ReadDebugDirectoryInformation(UUID* uuid,
- DWORD* age,
- std::string* pdbname) const {
- NtHeadersType nt_headers;
- if (!ReadNtHeaders(&nt_headers, nullptr))
+ IMAGE_DATA_DIRECTORY data_directory;
+ if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, &data_directory))
return false;
- if (nt_headers.FileHeader.SizeOfOptionalHeader <
- offsetof(decltype(nt_headers.OptionalHeader),
- DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) +
- sizeof(nt_headers.OptionalHeader
- .DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG]) ||
- nt_headers.OptionalHeader.NumberOfRvaAndSizes <=
- IMAGE_DIRECTORY_ENTRY_DEBUG) {
- return false;
- }
-
- const IMAGE_DATA_DIRECTORY& data_directory =
- nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
- if (data_directory.VirtualAddress == 0 || data_directory.Size == 0)
- return false;
IMAGE_DEBUG_DIRECTORY debug_directory;
if (data_directory.Size % sizeof(debug_directory) != 0)
return false;
@@ -216,6 +182,83 @@ bool PEImageReader::ReadDebugDirectoryInformation(UUID* uuid,
return false;
}
+bool PEImageReader::VSFixedFileInfo(
+ VS_FIXEDFILEINFO* vs_fixed_file_info) const {
+ IMAGE_DATA_DIRECTORY data_directory;
+ if (!ImageDataDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE,
+ &data_directory)) {
+ return false;
+ }
+
+ PEImageResourceReader resource_reader;
+ if (!resource_reader.Initialize(
+ process_reader_, data_directory, module_range_, module_name_)) {
+ return false;
+ }
+
+ WinVMAddress address;
+ WinVMSize size;
+ if (!resource_reader.FindResourceByID(
+ reinterpret_cast<uint16_t>(VS_FILE_INFO),
+ VS_VERSION_INFO,
+ MAKELANGID(LANG_NEUTRAL, SUBLANG_NEUTRAL),
+ &address,
+ &size,
+ nullptr)) {
+ return false;
+ }
+
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms647001.aspx
+ struct VS_VERSIONINFO {
+ WORD wLength;
+ WORD wValueLength;
+ WORD wType;
+
+ // MSDN doesn’t show the [16], but this is in fact a 16-character string.
+ WCHAR szKey[16];
+
+ WORD Padding1;
+ VS_FIXEDFILEINFO Value;
+
+ // Don’t include Children or the Padding2 that precedes it, because they may
+ // not be present.
+ // WORD Padding2;
+ // WORD Children;
+ };
+ VS_VERSIONINFO version_info;
+
+ if (size < sizeof(version_info)) {
+ LOG(WARNING) << "version info size " << size
+ << " too small for structure of size " << sizeof(version_info)
+ << " in " << module_name_;
+ return false;
+ }
+
+ if (!CheckedReadMemory(address, sizeof(version_info), &version_info)) {
+ return false;
+ }
+
+ if (version_info.wLength < sizeof(version_info) ||
+ version_info.wValueLength < sizeof(version_info.Value) ||
scottmg 2015/11/26 21:29:59 != for this one rather than <, as if it's not our
Mark Mentovai 2015/12/01 18:48:00 scottmg wrote:
+ version_info.wType != 0 ||
+ wcsncmp(version_info.szKey,
+ L"VS_VERSION_INFO",
+ arraysize(version_info.szKey)) != 0) {
+ LOG(WARNING) << "unexpected VS_VERSIONINFO";
+ return false;
+ }
+
+ if (version_info.Value.dwSignature != VS_FFI_SIGNATURE ||
+ version_info.Value.dwStrucVersion != VS_FFI_STRUCVERSION) {
+ LOG(WARNING) << "unexpected VS_FIXEDFILEINFO";
+ return false;
+ }
+
+ *vs_fixed_file_info = version_info.Value;
+ vs_fixed_file_info->dwFileFlags &= vs_fixed_file_info->dwFileFlagsMask;
+ return true;
+}
+
template <class NtHeadersType>
bool PEImageReader::ReadNtHeaders(NtHeadersType* nt_headers,
WinVMAddress* nt_headers_address) const {
@@ -282,17 +325,49 @@ bool PEImageReader::GetSectionByName(const std::string& name,
return false;
}
+bool PEImageReader::ImageDataDirectoryEntry(size_t index,
+ IMAGE_DATA_DIRECTORY* entry) const {
+ bool rv;
+ if (process_reader_->Is64Bit()) {
+ rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS64>(index, entry);
+ } else {
+ rv = ImageDataDirectoryEntryT<IMAGE_NT_HEADERS32>(index, entry);
+ }
+
+ return rv && entry->VirtualAddress != 0 && entry->Size != 0;
+}
+
+template <class NtHeadersType>
+bool PEImageReader::ImageDataDirectoryEntryT(
+ size_t index,
+ IMAGE_DATA_DIRECTORY* entry) const {
+ NtHeadersType nt_headers;
+ if (!ReadNtHeaders(&nt_headers, nullptr)) {
+ return false;
+ }
+
+ if (nt_headers.FileHeader.SizeOfOptionalHeader <
+ offsetof(decltype(nt_headers.OptionalHeader), DataDirectory[index]) +
+ sizeof(nt_headers.OptionalHeader.DataDirectory[index]) ||
+ nt_headers.OptionalHeader.NumberOfRvaAndSizes <= index) {
+ return false;
+ }
+
+ *entry = nt_headers.OptionalHeader.DataDirectory[index];
+ return true;
+}
+
bool PEImageReader::CheckedReadMemory(WinVMAddress address,
WinVMSize size,
void* into) const {
CheckedWinAddressRange read_range(process_reader_->Is64Bit(), address, size);
if (!read_range.IsValid()) {
- LOG(WARNING) << "invalid read range: " << RangeToString(read_range);
+ LOG(WARNING) << "invalid read range: " << read_range.AsString();
return false;
}
if (!module_range_.ContainsRange(read_range)) {
LOG(WARNING) << "attempt to read outside of module " << module_name_
- << " at range: " << RangeToString(read_range);
+ << " at range: " << read_range.AsString();
return false;
}
return process_reader_->ReadMemory(address, size, into);

Powered by Google App Engine
This is Rietveld 408576698