mirror of
https://github.com/yuzu-emu/breakpad.git
synced 2025-07-04 03:18:23 +00:00
Update MDRawMiscInfo to support version 5 of the MINIDUMP_MISC_INFO_N structure.
The routines used to read from the structure were also modified to accomodate for unknown future versions by skipping over the unsupported part instead of failing. R=ted.mielczarek@gmail.com Review URL: https://codereview.chromium.org/2109063004/ .
This commit is contained in:
parent
13c634f6a1
commit
c9f80bf1a8
|
@ -721,6 +721,41 @@ typedef struct {
|
||||||
/* MAX_PATH from windef.h */
|
/* MAX_PATH from windef.h */
|
||||||
#define MD_MAX_PATH 260
|
#define MD_MAX_PATH 260
|
||||||
|
|
||||||
|
/* For MDXStateConfigFeatureMscInfo.features */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
} MDXStateFeature;
|
||||||
|
|
||||||
|
/* For MDXStateConfigFeatureMscInfo.enabled_features from winnt.h */
|
||||||
|
typedef enum {
|
||||||
|
MD_XSTATE_LEGACY_FLOATING_POINT = 0, /* XSTATE_LEGACY_FLOATING_POINT */
|
||||||
|
MD_XSTATE_LEGACY_SSE = 1, /* XSTATE_LEGACY_SSE */
|
||||||
|
MD_XSTATE_GSSE = 2, /* XSTATE_GSSE */
|
||||||
|
MD_XSTATE_AVX = MD_XSTATE_GSSE, /* XSTATE_AVX */
|
||||||
|
MD_XSTATE_MPX_BNDREGS = 3, /* XSTATE_MPX_BNDREGS */
|
||||||
|
MD_XSTATE_MPX_BNDCSR = 4, /* XSTATE_MPX_BNDCSR */
|
||||||
|
MD_XSTATE_AVX512_KMASK = 5, /* XSTATE_AVX512_KMASK */
|
||||||
|
MD_XSTATE_AVX512_ZMM_H = 6, /* XSTATE_AVX512_ZMM_H */
|
||||||
|
MD_XSTATE_AVX512_ZMM = 7, /* XSTATE_AVX512_ZMM */
|
||||||
|
MD_XSTATE_IPT = 8, /* XSTATE_IPT */
|
||||||
|
MD_XSTATE_LWP = 62 /* XSTATE_LWP */
|
||||||
|
} MDXStateFeatureFlag;
|
||||||
|
|
||||||
|
/* MAXIMUM_XSTATE_FEATURES from winnt.h */
|
||||||
|
#define MD_MAXIMUM_XSTATE_FEATURES 64
|
||||||
|
|
||||||
|
/* For MDRawMiscInfo.xstate_data */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t size_of_info;
|
||||||
|
uint32_t context_size;
|
||||||
|
/* An entry in the features array is valid only if the corresponding bit in
|
||||||
|
* the enabled_features flag is set. */
|
||||||
|
uint64_t enabled_features;
|
||||||
|
MDXStateFeature features[MD_MAXIMUM_XSTATE_FEATURES];
|
||||||
|
} MDXStateConfigFeatureMscInfo;
|
||||||
|
|
||||||
|
|
||||||
/* The miscellaneous information stream contains a variety
|
/* The miscellaneous information stream contains a variety
|
||||||
* of small pieces of information. A member is valid if
|
* of small pieces of information. A member is valid if
|
||||||
* it's within the available size and its corresponding
|
* it's within the available size and its corresponding
|
||||||
|
@ -781,9 +816,22 @@ typedef struct {
|
||||||
* MD_MISCINFO_FLAGS1_BUILDSTRING. */
|
* MD_MISCINFO_FLAGS1_BUILDSTRING. */
|
||||||
uint16_t build_string[MD_MAX_PATH]; /* UTF-16-encoded, 0-terminated */
|
uint16_t build_string[MD_MAX_PATH]; /* UTF-16-encoded, 0-terminated */
|
||||||
uint16_t dbg_bld_str[40]; /* UTF-16-encoded, 0-terminated */
|
uint16_t dbg_bld_str[40]; /* UTF-16-encoded, 0-terminated */
|
||||||
|
|
||||||
|
/* The following fields are not present in MINIDUMP_MISC_INFO_4 but are
|
||||||
|
* in MINIDUMP_MISC_INFO_5. When this struct is populated, these values
|
||||||
|
* may not be set. Use flags1 and size_of_info to determine whether these
|
||||||
|
* values are present. */
|
||||||
|
|
||||||
|
/* The following field has its own flags for establishing the validity of
|
||||||
|
* the structure's contents.*/
|
||||||
|
MDXStateConfigFeatureMscInfo xstate_data;
|
||||||
|
|
||||||
|
/* The following field is only valid if flags1 contains
|
||||||
|
* MD_MISCINFO_FLAGS1_PROCESS_COOKIE. */
|
||||||
|
uint32_t process_cookie;
|
||||||
} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
|
} MDRawMiscInfo; /* MINIDUMP_MISC_INFO, MINIDUMP_MISC_INFO_2,
|
||||||
* MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4,
|
* MINIDUMP_MISC_INFO_3, MINIDUMP_MISC_INFO_4,
|
||||||
* MINIDUMP_MISC_INFO_N */
|
* MINIDUMP_MISC_INFO_5, MINIDUMP_MISC_INFO_N */
|
||||||
|
|
||||||
static const size_t MD_MISCINFO_SIZE =
|
static const size_t MD_MISCINFO_SIZE =
|
||||||
offsetof(MDRawMiscInfo, processor_max_mhz);
|
offsetof(MDRawMiscInfo, processor_max_mhz);
|
||||||
|
@ -791,7 +839,14 @@ static const size_t MD_MISCINFO2_SIZE =
|
||||||
offsetof(MDRawMiscInfo, process_integrity_level);
|
offsetof(MDRawMiscInfo, process_integrity_level);
|
||||||
static const size_t MD_MISCINFO3_SIZE =
|
static const size_t MD_MISCINFO3_SIZE =
|
||||||
offsetof(MDRawMiscInfo, build_string[0]);
|
offsetof(MDRawMiscInfo, build_string[0]);
|
||||||
static const size_t MD_MISCINFO4_SIZE = sizeof(MDRawMiscInfo);
|
static const size_t MD_MISCINFO4_SIZE =
|
||||||
|
offsetof(MDRawMiscInfo, xstate_data);
|
||||||
|
/* Version 5 of the MDRawMiscInfo structure is not a multiple of 8 in size and
|
||||||
|
* yet it contains some 8-bytes sized fields. This causes many compilers to
|
||||||
|
* round the structure size up to a multiple of 8 by adding padding at the end.
|
||||||
|
* The following hack is thus required for matching the proper on-disk size. */
|
||||||
|
static const size_t MD_MISCINFO5_SIZE =
|
||||||
|
offsetof(MDRawMiscInfo, process_cookie) + sizeof(uint32_t);
|
||||||
|
|
||||||
/* For (MDRawMiscInfo).flags1. These values indicate which fields in the
|
/* For (MDRawMiscInfo).flags1. These values indicate which fields in the
|
||||||
* MDRawMiscInfoStructure are valid. */
|
* MDRawMiscInfoStructure are valid. */
|
||||||
|
@ -812,6 +867,8 @@ typedef enum {
|
||||||
/* MINIDUMP_MISC3_PROTECTED_PROCESS */
|
/* MINIDUMP_MISC3_PROTECTED_PROCESS */
|
||||||
MD_MISCINFO_FLAGS1_BUILDSTRING = 0x00000100,
|
MD_MISCINFO_FLAGS1_BUILDSTRING = 0x00000100,
|
||||||
/* MINIDUMP_MISC4_BUILDSTRING */
|
/* MINIDUMP_MISC4_BUILDSTRING */
|
||||||
|
MD_MISCINFO_FLAGS1_PROCESS_COOKIE = 0x00000200,
|
||||||
|
/* MINIDUMP_MISC5_PROCESS_COOKIE */
|
||||||
} MDMiscInfoFlags1;
|
} MDMiscInfoFlags1;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -197,6 +197,21 @@ static inline void Swap(MDSystemTime* system_time) {
|
||||||
Swap(&system_time->milliseconds);
|
Swap(&system_time->milliseconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void Swap(MDXStateFeature* xstate_feature) {
|
||||||
|
Swap(&xstate_feature->offset);
|
||||||
|
Swap(&xstate_feature->size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) {
|
||||||
|
Swap(&xstate_feature_info->size_of_info);
|
||||||
|
Swap(&xstate_feature_info->context_size);
|
||||||
|
Swap(&xstate_feature_info->enabled_features);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) {
|
||||||
|
Swap(&xstate_feature_info->features[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static inline void Swap(uint16_t* data, size_t size_in_bytes) {
|
static inline void Swap(uint16_t* data, size_t size_in_bytes) {
|
||||||
size_t data_length = size_in_bytes / sizeof(data[0]);
|
size_t data_length = size_in_bytes / sizeof(data[0]);
|
||||||
for (size_t i = 0; i < data_length; i++) {
|
for (size_t i = 0; i < data_length; i++) {
|
||||||
|
@ -3508,22 +3523,46 @@ MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump)
|
||||||
bool MinidumpMiscInfo::Read(uint32_t expected_size) {
|
bool MinidumpMiscInfo::Read(uint32_t expected_size) {
|
||||||
valid_ = false;
|
valid_ = false;
|
||||||
|
|
||||||
|
size_t padding = 0;
|
||||||
if (expected_size != MD_MISCINFO_SIZE &&
|
if (expected_size != MD_MISCINFO_SIZE &&
|
||||||
expected_size != MD_MISCINFO2_SIZE &&
|
expected_size != MD_MISCINFO2_SIZE &&
|
||||||
expected_size != MD_MISCINFO3_SIZE &&
|
expected_size != MD_MISCINFO3_SIZE &&
|
||||||
expected_size != MD_MISCINFO4_SIZE) {
|
expected_size != MD_MISCINFO4_SIZE &&
|
||||||
|
expected_size != MD_MISCINFO5_SIZE) {
|
||||||
|
if (expected_size > MD_MISCINFO5_SIZE) {
|
||||||
|
// Only read the part of the misc info structure we know how to handle
|
||||||
|
BPLOG(INFO) << "MinidumpMiscInfo size larger than expected "
|
||||||
|
<< expected_size << ", skipping over the unknown part";
|
||||||
|
padding = expected_size - MD_MISCINFO5_SIZE;
|
||||||
|
expected_size = MD_MISCINFO5_SIZE;
|
||||||
|
} else {
|
||||||
BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
|
BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size
|
||||||
<< " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
|
<< " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE
|
||||||
<< ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
|
<< ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE
|
||||||
<< ")";
|
<< ", " << MD_MISCINFO5_SIZE << ")";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
|
if (!minidump_->ReadBytes(&misc_info_, expected_size)) {
|
||||||
BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
|
BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (padding != 0) {
|
||||||
|
off_t saved_position = minidump_->Tell();
|
||||||
|
if (saved_position == -1) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMiscInfo could not tell the current position";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!minidump_->SeekSet(saved_position + padding)) {
|
||||||
|
BPLOG(ERROR) << "MinidumpMiscInfo could not seek past the miscellaneous "
|
||||||
|
<< "info structure";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (minidump_->swap()) {
|
if (minidump_->swap()) {
|
||||||
// Swap version 1 fields
|
// Swap version 1 fields
|
||||||
Swap(&misc_info_.size_of_info);
|
Swap(&misc_info_.size_of_info);
|
||||||
|
@ -3553,9 +3592,14 @@ bool MinidumpMiscInfo::Read(uint32_t expected_size) {
|
||||||
// Do not swap UTF-16 strings. The swap is done as part of the
|
// Do not swap UTF-16 strings. The swap is done as part of the
|
||||||
// conversion to UTF-8 (code follows below).
|
// conversion to UTF-8 (code follows below).
|
||||||
}
|
}
|
||||||
|
if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) {
|
||||||
|
// Swap version 5 fields
|
||||||
|
Swap(&misc_info_.xstate_data);
|
||||||
|
Swap(&misc_info_.process_cookie);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (expected_size != misc_info_.size_of_info) {
|
if (expected_size + padding != misc_info_.size_of_info) {
|
||||||
BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
|
BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " <<
|
||||||
expected_size << " != " << misc_info_.size_of_info;
|
expected_size << " != " << misc_info_.size_of_info;
|
||||||
return false;
|
return false;
|
||||||
|
@ -3705,6 +3749,35 @@ void MinidumpMiscInfo::Print() {
|
||||||
printf(" dbg_bld_str = (invalid)\n");
|
printf(" dbg_bld_str = (invalid)\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) {
|
||||||
|
// Print version 5 fields
|
||||||
|
if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_COOKIE) {
|
||||||
|
printf(" xstate_data.size_of_info = %d\n",
|
||||||
|
misc_info_.xstate_data.size_of_info);
|
||||||
|
printf(" xstate_data.context_size = %d\n",
|
||||||
|
misc_info_.xstate_data.context_size);
|
||||||
|
printf(" xstate_data.enabled_features = 0x%" PRIx64 "\n",
|
||||||
|
misc_info_.xstate_data.enabled_features);
|
||||||
|
for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) {
|
||||||
|
if (misc_info_.xstate_data.enabled_features & (1 << i)) {
|
||||||
|
printf(" xstate_data.features[%02zu] = { %d, %d }\n", i,
|
||||||
|
misc_info_.xstate_data.features[i].offset,
|
||||||
|
misc_info_.xstate_data.features[i].size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (misc_info_.xstate_data.enabled_features == 0) {
|
||||||
|
printf(" xstate_data.features[] = (empty)\n");
|
||||||
|
}
|
||||||
|
printf(" process_cookie = %d\n",
|
||||||
|
misc_info_.process_cookie);
|
||||||
|
} else {
|
||||||
|
printf(" xstate_data.size_of_info = (invalid)\n");
|
||||||
|
printf(" xstate_data.context_size = (invalid)\n");
|
||||||
|
printf(" xstate_data.enabled_features = (invalid)\n");
|
||||||
|
printf(" xstate_data.features[] = (invalid)\n");
|
||||||
|
printf(" process_cookie = (invalid)\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue