Support MINIDUMP_MISC_INFO_5 defined in Windows 10

MINIDUMP_MISC_INFO_5 can carry information about extended XSTATE state
components and the process cookie value.

I made some informed guesses about the precise meanings of some of the
attributes of the XSTATE stuff.

I don’t know what “process cookie” refers to yet. My guess is that it’s
the stack canary value, or something similar. But since this isn’t an
informed guess, I haven’t written it into the documentation.

Crashpad does not yet use either of these features.

BUG=crashpad:58

Change-Id: I614568287a01fec99d6cd60e378a6d6e20b4f48c
Reviewed-on: https://chromium-review.googlesource.com/409630
Reviewed-by: Scott Graham <scottmg@chromium.org>
Commit-Queue: Mark Mentovai <mark@chromium.org>
This commit is contained in:
Mark Mentovai 2017-03-01 12:59:24 -05:00 коммит произвёл Commit Bot
Родитель 440b7e2374
Коммит f848952e05
5 изменённых файлов: 236 добавлений и 43 удалений

Просмотреть файл

@ -164,7 +164,7 @@ enum MINIDUMP_STREAM_TYPE {
UnloadedModuleListStream = 14,
//! \brief The stream type for MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
//! MINIDUMP_MISC_INFO_3, and MINIDUMP_MISC_INFO_4.
//! MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4, and MINIDUMP_MISC_INFO_5.
//!
//! More recent versions of this stream are supersets of earlier versions.
//!
@ -753,6 +753,33 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_UNLOADED_MODULE_LIST {
uint32_t NumberOfEntries;
};
//! \brief Information about XSAVE-managed state stored within CPU-specific
//! context structures.
struct __attribute__((packed, aligned(4))) XSTATE_CONFIG_FEATURE_MSC_INFO {
//! \brief The size of this structure, in bytes. This value is
//! `sizeof(XSTATE_CONFIG_FEATURE_MSC_INFO)`.
uint32_t SizeOfInfo;
//! \brief The size of a CPU-specific context structure carrying all XSAVE
//! state components described by this structure.
//!
//! Equivalent to the value returned by `InitializeContext()` in \a
//! ContextLength.
uint32_t ContextSize;
//! \brief The XSAVE state-component bitmap, XSAVE_BV.
//!
//! See Intel Software Developers Manual, Volume 1: Basic Architecture
//! (253665-060), 13.4.2 “XSAVE Header”.
uint64_t EnabledFeatures;
//! \brief The location of each state component within a CPU-specific context
//! structure.
//!
//! This array is indexed by bit position numbers used in #EnabledFeatures.
XSTATE_FEATURE Features[MAXIMUM_XSTATE_FEATURES];
};
//! \anchor MINIDUMP_MISCx
//! \name MINIDUMP_MISC*
//!
@ -805,6 +832,10 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_UNLOADED_MODULE_LIST {
//! - MINIDUMP_MISC_INFO_4::BuildString
//! - MINIDUMP_MISC_INFO_4::DbgBldStr
#define MINIDUMP_MISC4_BUILDSTRING 0x00000100
//! \brief MINIDUMP_MISC_INFO_5::ProcessCookie is valid.
#define MINIDUMP_MISC5_PROCESS_COOKIE 0x00000200
//! \}
//! \brief Information about the process that the minidump file contains a
@ -814,6 +845,7 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_UNLOADED_MODULE_LIST {
//! \sa MINIDUMP_MISC_INFO_2
//! \sa MINIDUMP_MISC_INFO_3
//! \sa MINIDUMP_MISC_INFO_4
//! \sa MINIDUMP_MISC_INFO_5
//! \sa MINIDUMP_MISC_INFO_N
struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO {
//! \brief The size of the structure.
@ -854,6 +886,7 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO {
//! \sa MINIDUMP_MISC_INFO
//! \sa MINIDUMP_MISC_INFO_3
//! \sa MINIDUMP_MISC_INFO_4
//! \sa MINIDUMP_MISC_INFO_5
//! \sa MINIDUMP_MISC_INFO_N
struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_2
: public MINIDUMP_MISC_INFO {
@ -885,6 +918,7 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_2
//! \sa MINIDUMP_MISC_INFO
//! \sa MINIDUMP_MISC_INFO_2
//! \sa MINIDUMP_MISC_INFO_4
//! \sa MINIDUMP_MISC_INFO_5
//! \sa MINIDUMP_MISC_INFO_N
struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_3
: public MINIDUMP_MISC_INFO_2 {
@ -946,6 +980,7 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_3
//! \sa MINIDUMP_MISC_INFO
//! \sa MINIDUMP_MISC_INFO_2
//! \sa MINIDUMP_MISC_INFO_3
//! \sa MINIDUMP_MISC_INFO_5
//! \sa MINIDUMP_MISC_INFO_N
struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_4
: public MINIDUMP_MISC_INFO_3 {
@ -968,8 +1003,31 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_4
base::char16 DbgBldStr[40];
};
//! \brief Information about the process that the minidump file contains a
//! snapshot of, as well as the system that hosted that process.
//!
//! This structure variant is used on Windows 10 and later.
//!
//! \sa \ref MINIDUMP_MISCx "MINIDUMP_MISC*"
//! \sa MINIDUMP_MISC_INFO
//! \sa MINIDUMP_MISC_INFO_2
//! \sa MINIDUMP_MISC_INFO_3
//! \sa MINIDUMP_MISC_INFO_4
//! \sa MINIDUMP_MISC_INFO_N
struct __attribute__((packed, aligned(4))) MINIDUMP_MISC_INFO_5
: public MINIDUMP_MISC_INFO_4 {
//! \brief Information about XSAVE-managed state stored within CPU-specific
//! context structures.
//!
//! This information can be used to locate state components within
//! CPU-specific context structures.
XSTATE_CONFIG_FEATURE_MSC_INFO XStateData;
uint32_t ProcessCookie;
};
//! \brief The latest known version of the MINIDUMP_MISC_INFO structure.
typedef MINIDUMP_MISC_INFO_4 MINIDUMP_MISC_INFO_N;
typedef MINIDUMP_MISC_INFO_5 MINIDUMP_MISC_INFO_N;
//! \brief Describes a region of memory.
struct __attribute__((packed, aligned(4))) MINIDUMP_MEMORY_INFO {

Просмотреть файл

@ -112,6 +112,66 @@
#define PF_RDTSCP_INSTRUCTION_AVAILABLE 32
//! \}
//! \anchor PAGE_x
//! \name PAGE_*
//!
//! \brief Memory protection constants for MINIDUMP_MEMORY_INFO::Protect and
//! MINIDUMP_MEMORY_INFO::AllocationProtect.
//! \{
#define PAGE_NOACCESS 0x1
#define PAGE_READONLY 0x2
#define PAGE_READWRITE 0x4
#define PAGE_WRITECOPY 0x8
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
//! \}
//! \anchor MEM_x
//! \name MEM_*
//!
//! \brief Memory state and type constants for MINIDUMP_MEMORY_INFO::State and
//! MINIDUMP_MEMORY_INFO::Type.
//! \{
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
#define MEM_DECOMMIT 0x4000
#define MEM_RELEASE 0x8000
#define MEM_FREE 0x10000
#define MEM_PRIVATE 0x20000
#define MEM_MAPPED 0x40000
#define MEM_RESET 0x80000
//! \}
//! \brief The maximum number of distinct identifiable features that could
//! possibly be carried in an XSAVE area.
//!
//! This corresponds to the number of bits in the XSAVE state-component bitmap,
//! XSAVE_BV. See Intel Software Developers Manual, Volume 1: Basic
//! Architecture (253665-060), 13.4.2 “XSAVE Header”.
#define MAXIMUM_XSTATE_FEATURES (64)
//! \brief The location of a single state component within an XSAVE area.
struct XSTATE_FEATURE {
//! \brief The location of a state component within a CPU-specific context
//! structure.
//!
//! This is equivalent to the difference (`ptrdiff_t`) between the return
//! value of `LocateXStateFeature()` and its \a Context argument.
uint32_t Offset;
//! \brief The size of a state component with a CPU-specific context
//! structure.
//!
//! This is equivalent to the size returned by `LocateXStateFeature()` in \a
//! Length.
uint32_t Size;
};
//! \anchor IMAGE_DEBUG_MISC_x
//! \name IMAGE_DEBUG_MISC_*
//!
@ -187,39 +247,4 @@ struct IMAGE_DEBUG_MISC {
#define VER_PLATFORM_WIN32_NT 2
//! \}
//! \anchor PAGE_x
//! \name PAGE_*
//!
//! \brief Memory protection constants for MINIDUMP_MEMORY_INFO::Protect and
//! MINIDUMP_MEMORY_INFO::AllocationProtect.
//! \{
#define PAGE_NOACCESS 0x1
#define PAGE_READONLY 0x2
#define PAGE_READWRITE 0x4
#define PAGE_WRITECOPY 0x8
#define PAGE_EXECUTE 0x10
#define PAGE_EXECUTE_READ 0x20
#define PAGE_EXECUTE_READWRITE 0x40
#define PAGE_EXECUTE_WRITECOPY 0x80
#define PAGE_GUARD 0x100
#define PAGE_NOCACHE 0x200
#define PAGE_WRITECOMBINE 0x400
//! \}
//! \anchor MEM_x
//! \name MEM_*
//!
//! \brief Memory state and type constants for MINIDUMP_MEMORY_INFO::State and
//! MINIDUMP_MEMORY_INFO::Type.
//! \{
#define MEM_COMMIT 0x1000
#define MEM_RESERVE 0x2000
#define MEM_DECOMMIT 0x4000
#define MEM_RELEASE 0x8000
#define MEM_FREE 0x10000
#define MEM_PRIVATE 0x20000
#define MEM_MAPPED 0x40000
#define MEM_RESET 0x80000
//! \}
#endif // CRASHPAD_COMPAT_NON_WIN_WINNT_H_

Просмотреть файл

@ -145,7 +145,7 @@ std::string MinidumpMiscInfoDebugBuildString() {
} // namespace internal
MinidumpMiscInfoWriter::MinidumpMiscInfoWriter()
: MinidumpStreamWriter(), misc_info_() {
: MinidumpStreamWriter(), misc_info_(), has_xstate_data_(false) {
}
MinidumpMiscInfoWriter::~MinidumpMiscInfoWriter() {
@ -330,6 +330,21 @@ void MinidumpMiscInfoWriter::SetBuildString(
debug_build_string);
}
void MinidumpMiscInfoWriter::SetXStateData(
const XSTATE_CONFIG_FEATURE_MSC_INFO& xstate_data) {
DCHECK_EQ(state(), kStateMutable);
misc_info_.XStateData = xstate_data;
has_xstate_data_ = true;
}
void MinidumpMiscInfoWriter::SetProcessCookie(uint32_t process_cookie) {
DCHECK_EQ(state(), kStateMutable);
misc_info_.ProcessCookie = process_cookie;
misc_info_.Flags1 |= MINIDUMP_MISC5_PROCESS_COOKIE;
}
bool MinidumpMiscInfoWriter::Freeze() {
DCHECK_EQ(state(), kStateMutable);
@ -365,6 +380,9 @@ MinidumpStreamType MinidumpMiscInfoWriter::StreamType() const {
size_t MinidumpMiscInfoWriter::CalculateSizeOfObjectFromFlags() const {
DCHECK_GE(state(), kStateFrozen);
if (has_xstate_data_ || (misc_info_.Flags1 & MINIDUMP_MISC5_PROCESS_COOKIE)) {
return sizeof(MINIDUMP_MISC_INFO_5);
}
if (misc_info_.Flags1 & MINIDUMP_MISC4_BUILDSTRING) {
return sizeof(MINIDUMP_MISC_INFO_4);
}

Просмотреть файл

@ -51,10 +51,10 @@ std::string MinidumpMiscInfoDebugBuildString();
//! minidump file.
//!
//! The actual stream written will be a MINIDUMP_MISC_INFO,
//! MINIDUMP_MISC_INFO_2, MINIDUMP_MISC_INFO_3, or MINIDUMP_MISC_INFO_4 stream.
//! Later versions of MINIDUMP_MISC_INFO are supersets of earlier versions. The
//! earliest version that supports all of the information that an object of this
//! class contains will be used.
//! MINIDUMP_MISC_INFO_2, MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4, or
//! MINIDUMP_MISC_INFO_5 stream. Later versions of MINIDUMP_MISC_INFO are
//! supersets of earlier versions. The earliest version that supports all of the
//! information that an object of this class contains will be used.
class MinidumpMiscInfoWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpMiscInfoWriter();
@ -107,6 +107,15 @@ class MinidumpMiscInfoWriter final : public internal::MinidumpStreamWriter {
void SetBuildString(const std::string& build_string,
const std::string& debug_build_string);
// TODO(mark): Provide a better interface than this. Dont force callers to
// build their own XSTATE_CONFIG_FEATURE_MSC_INFO structure.
//
//! \brief Sets MINIDUMP_MISC_INFO_5::XStateData.
void SetXStateData(const XSTATE_CONFIG_FEATURE_MSC_INFO& xstate_data);
//! \brief Sets the field referenced by #MINIDUMP_MISC5_PROCESS_COOKIE.
void SetProcessCookie(uint32_t process_cookie);
protected:
// MinidumpWritable:
bool Freeze() override;
@ -123,6 +132,7 @@ class MinidumpMiscInfoWriter final : public internal::MinidumpStreamWriter {
size_t CalculateSizeOfObjectFromFlags() const;
MINIDUMP_MISC_INFO_N misc_info_;
bool has_xstate_data_;
DISALLOW_COPY_AND_ASSIGN(MinidumpMiscInfoWriter);
};

Просмотреть файл

@ -21,9 +21,11 @@
#include <utility>
#include "base/compiler_specific.h"
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string16.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "gtest/gtest.h"
#include "minidump/minidump_file_writer.h"
@ -164,6 +166,29 @@ void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_4>(
}
}
template <>
void ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_5>(
const MINIDUMP_MISC_INFO_5* expected,
const MINIDUMP_MISC_INFO_5* observed) {
ExpectMiscInfoEqual<MINIDUMP_MISC_INFO_4>(
reinterpret_cast<const MINIDUMP_MISC_INFO_4*>(expected),
reinterpret_cast<const MINIDUMP_MISC_INFO_4*>(observed));
EXPECT_EQ(expected->XStateData.SizeOfInfo, observed->XStateData.SizeOfInfo);
EXPECT_EQ(expected->XStateData.ContextSize, observed->XStateData.ContextSize);
EXPECT_EQ(expected->XStateData.EnabledFeatures,
observed->XStateData.EnabledFeatures);
for (size_t feature_index = 0;
feature_index < arraysize(observed->XStateData.Features);
++feature_index) {
SCOPED_TRACE(base::StringPrintf("feature_index %" PRIuS, feature_index));
EXPECT_EQ(expected->XStateData.Features[feature_index].Offset,
observed->XStateData.Features[feature_index].Offset);
EXPECT_EQ(expected->XStateData.Features[feature_index].Size,
observed->XStateData.Features[feature_index].Size);
}
EXPECT_EQ(expected->ProcessCookie, observed->ProcessCookie);
}
TEST(MinidumpMiscInfoWriter, Empty) {
MinidumpFileWriter minidump_file_writer;
auto misc_info_writer = base::WrapUnique(new MinidumpMiscInfoWriter());
@ -490,7 +515,7 @@ TEST(MinidumpMiscInfoWriter, BuildStringsOverflow) {
MinidumpFileWriter minidump_file_writer;
auto misc_info_writer = base::WrapUnique(new MinidumpMiscInfoWriter());
MINIDUMP_MISC_INFO_4 tmp;
MINIDUMP_MISC_INFO_N tmp;
ALLOW_UNUSED_LOCAL(tmp);
std::string build_string(arraysize(tmp.BuildString) + 1, 'B');
std::string debug_build_string(arraysize(tmp.DbgBldStr), 'D');
@ -520,6 +545,63 @@ TEST(MinidumpMiscInfoWriter, BuildStringsOverflow) {
ExpectMiscInfoEqual(&expected, observed);
}
TEST(MinidumpMiscInfoWriter, XStateData) {
MinidumpFileWriter minidump_file_writer;
auto misc_info_writer = base::WrapUnique(new MinidumpMiscInfoWriter());
const XSTATE_CONFIG_FEATURE_MSC_INFO kXStateData = {
sizeof(XSTATE_CONFIG_FEATURE_MSC_INFO),
1024,
0x000000000000005f,
{
{0, 512},
{512, 256},
{768, 128},
{896, 64},
{960, 32},
{0, 0},
{992, 32},
}};
misc_info_writer->SetXStateData(kXStateData);
minidump_file_writer.AddStream(std::move(misc_info_writer));
StringFile string_file;
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
const MINIDUMP_MISC_INFO_5* observed = nullptr;
ASSERT_NO_FATAL_FAILURE(GetMiscInfoStream(string_file.string(), &observed));
MINIDUMP_MISC_INFO_5 expected = {};
expected.XStateData = kXStateData;
ExpectMiscInfoEqual(&expected, observed);
}
TEST(MinidumpMiscInfoWriter, ProcessCookie) {
MinidumpFileWriter minidump_file_writer;
auto misc_info_writer = base::WrapUnique(new MinidumpMiscInfoWriter());
const uint32_t kProcessCookie = 0x12345678;
misc_info_writer->SetProcessCookie(kProcessCookie);
minidump_file_writer.AddStream(std::move(misc_info_writer));
StringFile string_file;
ASSERT_TRUE(minidump_file_writer.WriteEverything(&string_file));
const MINIDUMP_MISC_INFO_5* observed = nullptr;
ASSERT_NO_FATAL_FAILURE(GetMiscInfoStream(string_file.string(), &observed));
MINIDUMP_MISC_INFO_5 expected = {};
expected.Flags1 = MINIDUMP_MISC5_PROCESS_COOKIE;
expected.ProcessCookie = kProcessCookie;
ExpectMiscInfoEqual(&expected, observed);
}
TEST(MinidumpMiscInfoWriter, Everything) {
MinidumpFileWriter minidump_file_writer;
auto misc_info_writer = base::WrapUnique(new MinidumpMiscInfoWriter());