mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-17 08:33:54 +00:00
Implement ModuleSnapshotWin::UUID
Reads CodeView PDB GUID from Debug Directory of PE header. R=mark@chromium.org BUG=crashpad:1 Review URL: https://codereview.chromium.org/1311003003 .
This commit is contained in:
parent
78bba8808b
commit
3ef04d14f2
@ -535,16 +535,14 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MODULE {
|
|||||||
VS_FIXEDFILEINFO VersionInfo;
|
VS_FIXEDFILEINFO VersionInfo;
|
||||||
|
|
||||||
//! \brief A pointer to the module’s CodeView record, typically a link to its
|
//! \brief A pointer to the module’s CodeView record, typically a link to its
|
||||||
//! debugging information in crashpad::MinidumpModuleCodeViewRecordPDB70
|
//! debugging information in crashpad::CodeViewRecordPDB70 format.
|
||||||
//! format.
|
|
||||||
//!
|
//!
|
||||||
//! The specific format of the CodeView record is indicated by its signature,
|
//! The specific format of the CodeView record is indicated by its signature,
|
||||||
//! the first 32-bit value in the structure. For links to debugging
|
//! the first 32-bit value in the structure. For links to debugging
|
||||||
//! information in contemporary usage, this is normally a
|
//! information in contemporary usage, this is normally a
|
||||||
//! crashpad::MinidumpModuleCodeViewRecordPDB70 structure, but may be a
|
//! crashpad::CodeViewRecordPDB70 structure, but may be a
|
||||||
//! crashpad::MinidumpModuleCodeViewRecordPDB20 structure instead. These
|
//! crashpad::CodeViewRecordPDB20 structure instead. These structures identify
|
||||||
//! structures identify a link to debugging data within a `.pdb` (Program
|
//! a link to debugging data within a `.pdb` (Program Database) file. See <a
|
||||||
//! Database) file. See <a
|
|
||||||
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
||||||
//! Debug Information</a>, PDB Files.
|
//! Debug Information</a>, PDB Files.
|
||||||
//!
|
//!
|
||||||
@ -565,8 +563,8 @@ struct __attribute__((packed, aligned(4))) MINIDUMP_MODULE {
|
|||||||
//! On Windows, the CodeView record is taken from a module’s
|
//! On Windows, the CodeView record is taken from a module’s
|
||||||
//! IMAGE_DEBUG_DIRECTORY entry whose Type field has the value
|
//! IMAGE_DEBUG_DIRECTORY entry whose Type field has the value
|
||||||
//! IMAGE_DEBUG_TYPE_CODEVIEW (`2`), if any. Records in
|
//! IMAGE_DEBUG_TYPE_CODEVIEW (`2`), if any. Records in
|
||||||
//! crashpad::MinidumpModuleCodeViewRecordPDB70 format are generated by Visual
|
//! crashpad::CodeViewRecordPDB70 format are generated by Visual Studio .NET
|
||||||
//! Studio .NET (2002) (version 7.0) and later.
|
//! (2002) (version 7.0) and later.
|
||||||
//!
|
//!
|
||||||
//! When the CodeView record is not present, the fields of this
|
//! When the CodeView record is not present, the fields of this
|
||||||
//! MINIDUMP_LOCATION_DESCRIPTOR will be `0`.
|
//! MINIDUMP_LOCATION_DESCRIPTOR will be `0`.
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
const uint32_t MinidumpModuleCodeViewRecordPDB20::kSignature;
|
|
||||||
const uint32_t MinidumpModuleCodeViewRecordPDB70::kSignature;
|
|
||||||
const uint32_t MinidumpModuleCrashpadInfo::kVersion;
|
const uint32_t MinidumpModuleCrashpadInfo::kVersion;
|
||||||
const uint32_t MinidumpCrashpadInfo::kVersion;
|
const uint32_t MinidumpCrashpadInfo::kVersion;
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "base/compiler_specific.h"
|
#include "base/compiler_specific.h"
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
#include "util/misc/pdb_structures.h"
|
||||||
#include "util/misc/uuid.h"
|
#include "util/misc/uuid.h"
|
||||||
|
|
||||||
// C4200 is "nonstandard extension used : zero-sized array in struct/union".
|
// C4200 is "nonstandard extension used : zero-sized array in struct/union".
|
||||||
@ -216,112 +217,6 @@ enum MinidumpOS : uint32_t {
|
|||||||
kMinidumpOSUnknown = 0xffffffff,
|
kMinidumpOSUnknown = 0xffffffff,
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief A CodeView record linking to a `.pdb` 2.0 file.
|
|
||||||
//!
|
|
||||||
//! This format provides an indirect link to debugging data by referencing an
|
|
||||||
//! external `.pdb` file by its name, timestamp, and age. This structure may be
|
|
||||||
//! pointed to by MINIDUMP_MODULE::CvRecord. It has been superseded by
|
|
||||||
//! MinidumpModuleCodeViewRecordPDB70.
|
|
||||||
//!
|
|
||||||
//! For more information about this structure and format, see <a
|
|
||||||
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
|
||||||
//! Debug Information</a>, PDB Files, and <a
|
|
||||||
//! href="http://undocumented.rawol.com/sbs-w2k-1-windows-2000-debugging-support.pdf#page=63">Undocumented
|
|
||||||
//! Windows 2000 Secrets</a>, Windows 2000 Debugging Support/Microsoft Symbol
|
|
||||||
//! File Internals/CodeView Subsections.
|
|
||||||
//!
|
|
||||||
//! \sa IMAGE_DEBUG_MISC
|
|
||||||
struct MinidumpModuleCodeViewRecordPDB20 {
|
|
||||||
//! \brief The magic number identifying this structure version, stored in
|
|
||||||
//! #signature.
|
|
||||||
//!
|
|
||||||
//! In a hex dump, this will appear as “NB10” when produced by a little-endian
|
|
||||||
//! machine.
|
|
||||||
static const uint32_t kSignature = '01BN';
|
|
||||||
|
|
||||||
//! \brief The magic number identifying this structure version, the value of
|
|
||||||
//! #kSignature.
|
|
||||||
uint32_t signature;
|
|
||||||
|
|
||||||
//! \brief The offset to CodeView data.
|
|
||||||
//!
|
|
||||||
//! In this structure, this field always has the value `0` because no CodeView
|
|
||||||
//! data is present, there is only a link to CodeView data stored in an
|
|
||||||
//! external file.
|
|
||||||
uint32_t offset;
|
|
||||||
|
|
||||||
//! \brief The time that the `.pdb` file was created, in `time_t` format, the
|
|
||||||
//! number of seconds since the POSIX epoch.
|
|
||||||
uint32_t timestamp;
|
|
||||||
|
|
||||||
//! \brief The revision of the `.pdb` file.
|
|
||||||
//!
|
|
||||||
//! A `.pdb` file’s age indicates incremental changes to it. When a `.pdb`
|
|
||||||
//! file is created, it has age `1`, and subsequent updates increase this
|
|
||||||
//! value.
|
|
||||||
uint32_t age;
|
|
||||||
|
|
||||||
//! \brief The path or file name of the `.pdb` file associated with the
|
|
||||||
//! module.
|
|
||||||
//!
|
|
||||||
//! This is a NUL-terminated string. On Windows, it will be encoded in the
|
|
||||||
//! code page of the system that linked the module. On other operating
|
|
||||||
//! systems, UTF-8 may be used.
|
|
||||||
uint8_t pdb_name[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \brief A CodeView record linking to a `.pdb` 7.0 file.
|
|
||||||
//!
|
|
||||||
//! This format provides an indirect link to debugging data by referencing an
|
|
||||||
//! external `.pdb` file by its name, %UUID, and age. This structure may be
|
|
||||||
//! pointed to by MINIDUMP_MODULE::CvRecord.
|
|
||||||
//!
|
|
||||||
//! For more information about this structure and format, see <a
|
|
||||||
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
|
||||||
//! Debug Information</a>, PDB Files.
|
|
||||||
//!
|
|
||||||
//! \sa MinidumpModuleCodeViewRecordPDB20
|
|
||||||
//! \sa IMAGE_DEBUG_MISC
|
|
||||||
struct MinidumpModuleCodeViewRecordPDB70 {
|
|
||||||
// UUID has a constructor, which makes it non-POD, which makes this structure
|
|
||||||
// non-POD. In order for the default constructor to zero-initialize other
|
|
||||||
// members, an explicit constructor must be provided.
|
|
||||||
MinidumpModuleCodeViewRecordPDB70()
|
|
||||||
: signature(),
|
|
||||||
uuid(),
|
|
||||||
age(),
|
|
||||||
pdb_name() {
|
|
||||||
}
|
|
||||||
|
|
||||||
//! \brief The magic number identifying this structure version, stored in
|
|
||||||
//! #signature.
|
|
||||||
//!
|
|
||||||
//! In a hex dump, this will appear as “RSDS” when produced by a little-endian
|
|
||||||
//! machine.
|
|
||||||
static const uint32_t kSignature = 'SDSR';
|
|
||||||
|
|
||||||
//! \brief The magic number identifying this structure version, the value of
|
|
||||||
//! #kSignature.
|
|
||||||
uint32_t signature;
|
|
||||||
|
|
||||||
//! \brief The `.pdb` file’s unique identifier.
|
|
||||||
UUID uuid;
|
|
||||||
|
|
||||||
//! \brief The revision of the `.pdb` file.
|
|
||||||
//!
|
|
||||||
//! A `.pdb` file’s age indicates incremental changes to it. When a `.pdb`
|
|
||||||
//! file is created, it has age `1`, and subsequent updates increase this
|
|
||||||
//! value.
|
|
||||||
uint32_t age;
|
|
||||||
|
|
||||||
//! \brief The path or file name of the `.pdb` file associated with the
|
|
||||||
//! module.
|
|
||||||
//!
|
|
||||||
//! This is a NUL-terminated string. On Windows, it will be encoded in the
|
|
||||||
//! code page of the system that linked the module. On other operating
|
|
||||||
//! systems, UTF-8 may be used.
|
|
||||||
uint8_t pdb_name[1];
|
|
||||||
};
|
|
||||||
|
|
||||||
//! \brief A list of ::RVA pointers.
|
//! \brief A list of ::RVA pointers.
|
||||||
struct ALIGNAS(4) PACKED MinidumpRVAList {
|
struct ALIGNAS(4) PACKED MinidumpRVAList {
|
||||||
|
@ -77,7 +77,7 @@ bool MinidumpModuleCodeViewRecordPDBLinkWriter<CodeViewRecordType>::WriteObject(
|
|||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB20>;
|
CodeViewRecordPDB20>;
|
||||||
|
|
||||||
MinidumpModuleCodeViewRecordPDB20Writer::
|
MinidumpModuleCodeViewRecordPDB20Writer::
|
||||||
~MinidumpModuleCodeViewRecordPDB20Writer() {
|
~MinidumpModuleCodeViewRecordPDB20Writer() {
|
||||||
@ -95,7 +95,7 @@ void MinidumpModuleCodeViewRecordPDB20Writer::SetTimestampAndAge(
|
|||||||
}
|
}
|
||||||
|
|
||||||
template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
template class internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB70>;
|
CodeViewRecordPDB70>;
|
||||||
|
|
||||||
MinidumpModuleCodeViewRecordPDB70Writer::
|
MinidumpModuleCodeViewRecordPDB70Writer::
|
||||||
~MinidumpModuleCodeViewRecordPDB70Writer() {
|
~MinidumpModuleCodeViewRecordPDB70Writer() {
|
||||||
|
@ -86,42 +86,38 @@ class MinidumpModuleCodeViewRecordPDBLinkWriter
|
|||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
//! \brief The writer for a MinidumpModuleCodeViewRecordPDB20 object in a
|
//! \brief The writer for a CodeViewRecordPDB20 object in a minidump file.
|
||||||
//! minidump file.
|
|
||||||
//!
|
//!
|
||||||
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer instead.
|
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer instead.
|
||||||
class MinidumpModuleCodeViewRecordPDB20Writer final
|
class MinidumpModuleCodeViewRecordPDB20Writer final
|
||||||
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB20> {
|
CodeViewRecordPDB20> {
|
||||||
public:
|
public:
|
||||||
MinidumpModuleCodeViewRecordPDB20Writer()
|
MinidumpModuleCodeViewRecordPDB20Writer()
|
||||||
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB20>() {}
|
CodeViewRecordPDB20>() {}
|
||||||
|
|
||||||
~MinidumpModuleCodeViewRecordPDB20Writer() override;
|
~MinidumpModuleCodeViewRecordPDB20Writer() override;
|
||||||
|
|
||||||
//! \brief Sets MinidumpModuleCodeViewRecordPDB20::timestamp and
|
//! \brief Sets CodeViewRecordPDB20::timestamp and CodeViewRecordPDB20::age.
|
||||||
//! MinidumpModuleCodeViewRecordPDB20::age.
|
|
||||||
void SetTimestampAndAge(time_t timestamp, uint32_t age);
|
void SetTimestampAndAge(time_t timestamp, uint32_t age);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordPDB20Writer);
|
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleCodeViewRecordPDB20Writer);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief The writer for a MinidumpModuleCodeViewRecordPDB70 object in a
|
//! \brief The writer for a CodeViewRecordPDB70 object in a minidump file.
|
||||||
//! minidump file.
|
|
||||||
class MinidumpModuleCodeViewRecordPDB70Writer final
|
class MinidumpModuleCodeViewRecordPDB70Writer final
|
||||||
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB70> {
|
CodeViewRecordPDB70> {
|
||||||
public:
|
public:
|
||||||
MinidumpModuleCodeViewRecordPDB70Writer()
|
MinidumpModuleCodeViewRecordPDB70Writer()
|
||||||
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
|
||||||
MinidumpModuleCodeViewRecordPDB70>() {}
|
CodeViewRecordPDB70>() {}
|
||||||
|
|
||||||
~MinidumpModuleCodeViewRecordPDB70Writer() override;
|
~MinidumpModuleCodeViewRecordPDB70Writer() override;
|
||||||
|
|
||||||
//! \brief Initializes the MinidumpModuleCodeViewRecordPDB70 based on \a
|
//! \brief Initializes the CodeViewRecordPDB70 based on \a module_snapshot.
|
||||||
//! module_snapshot.
|
|
||||||
//!
|
//!
|
||||||
//! \param[in] module_snapshot The module snapshot to use as source data.
|
//! \param[in] module_snapshot The module snapshot to use as source data.
|
||||||
//!
|
//!
|
||||||
@ -130,8 +126,7 @@ class MinidumpModuleCodeViewRecordPDB70Writer final
|
|||||||
//! methods after this method.
|
//! methods after this method.
|
||||||
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
|
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
|
||||||
|
|
||||||
//! \brief Sets MinidumpModuleCodeViewRecordPDB70::uuid and
|
//! \brief Sets CodeViewRecordPDB70::uuid and CodeViewRecordPDB70::age.
|
||||||
//! MinidumpModuleCodeViewRecordPDB70::age.
|
|
||||||
void SetUUIDAndAge(const UUID& uuid, uint32_t age) {
|
void SetUUIDAndAge(const UUID& uuid, uint32_t age) {
|
||||||
codeview_record()->uuid = uuid;
|
codeview_record()->uuid = uuid;
|
||||||
codeview_record()->age = age;
|
codeview_record()->age = age;
|
||||||
|
@ -100,10 +100,9 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
|||||||
std::string observed_pdb_name;
|
std::string observed_pdb_name;
|
||||||
if (expected_pdb_uuid) {
|
if (expected_pdb_uuid) {
|
||||||
// The CodeView record should be a PDB 7.0 link.
|
// The CodeView record should be a PDB 7.0 link.
|
||||||
const MinidumpModuleCodeViewRecordPDB70* codeview_pdb70_record =
|
const CodeViewRecordPDB70* codeview_pdb70_record =
|
||||||
MinidumpWritableAtLocationDescriptor<
|
MinidumpWritableAtLocationDescriptor<CodeViewRecordPDB70>(
|
||||||
MinidumpModuleCodeViewRecordPDB70>(file_contents,
|
file_contents, *codeview_record);
|
||||||
*codeview_record);
|
|
||||||
ASSERT_TRUE(codeview_pdb70_record);
|
ASSERT_TRUE(codeview_pdb70_record);
|
||||||
EXPECT_EQ(0,
|
EXPECT_EQ(0,
|
||||||
memcmp(expected_pdb_uuid,
|
memcmp(expected_pdb_uuid,
|
||||||
@ -113,14 +112,12 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
|||||||
|
|
||||||
observed_pdb_name.assign(
|
observed_pdb_name.assign(
|
||||||
reinterpret_cast<const char*>(&codeview_pdb70_record->pdb_name[0]),
|
reinterpret_cast<const char*>(&codeview_pdb70_record->pdb_name[0]),
|
||||||
codeview_record->DataSize -
|
codeview_record->DataSize - offsetof(CodeViewRecordPDB70, pdb_name));
|
||||||
offsetof(MinidumpModuleCodeViewRecordPDB70, pdb_name));
|
|
||||||
} else {
|
} else {
|
||||||
// The CodeView record should be a PDB 2.0 link.
|
// The CodeView record should be a PDB 2.0 link.
|
||||||
const MinidumpModuleCodeViewRecordPDB20* codeview_pdb20_record =
|
const CodeViewRecordPDB20* codeview_pdb20_record =
|
||||||
MinidumpWritableAtLocationDescriptor<
|
MinidumpWritableAtLocationDescriptor<CodeViewRecordPDB20>(
|
||||||
MinidumpModuleCodeViewRecordPDB20>(file_contents,
|
file_contents, *codeview_record);
|
||||||
*codeview_record);
|
|
||||||
ASSERT_TRUE(codeview_pdb20_record);
|
ASSERT_TRUE(codeview_pdb20_record);
|
||||||
EXPECT_EQ(static_cast<uint32_t>(expected_pdb_timestamp),
|
EXPECT_EQ(static_cast<uint32_t>(expected_pdb_timestamp),
|
||||||
codeview_pdb20_record->timestamp);
|
codeview_pdb20_record->timestamp);
|
||||||
@ -128,8 +125,7 @@ void ExpectCodeViewRecord(const MINIDUMP_LOCATION_DESCRIPTOR* codeview_record,
|
|||||||
|
|
||||||
observed_pdb_name.assign(
|
observed_pdb_name.assign(
|
||||||
reinterpret_cast<const char*>(&codeview_pdb20_record->pdb_name[0]),
|
reinterpret_cast<const char*>(&codeview_pdb20_record->pdb_name[0]),
|
||||||
codeview_record->DataSize -
|
codeview_record->DataSize - offsetof(CodeViewRecordPDB20, pdb_name));
|
||||||
offsetof(MinidumpModuleCodeViewRecordPDB20, pdb_name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for, and then remove, the NUL terminator.
|
// Check for, and then remove, the NUL terminator.
|
||||||
|
@ -291,21 +291,19 @@ const T* MinidumpCVPDBAtLocationDescriptor(
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCodeViewRecordPDB20*
|
const CodeViewRecordPDB20* MinidumpWritableAtLocationDescriptor<
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
CodeViewRecordPDB20>(const std::string& file_contents,
|
||||||
const std::string& file_contents,
|
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
return MinidumpCVPDBAtLocationDescriptor<CodeViewRecordPDB20>(file_contents,
|
||||||
return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
location);
|
||||||
file_contents, location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCodeViewRecordPDB70*
|
const CodeViewRecordPDB70* MinidumpWritableAtLocationDescriptor<
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
CodeViewRecordPDB70>(const std::string& file_contents,
|
||||||
const std::string& file_contents,
|
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location) {
|
return MinidumpCVPDBAtLocationDescriptor<CodeViewRecordPDB70>(file_contents,
|
||||||
return MinidumpCVPDBAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
location);
|
||||||
file_contents, location);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TestUInt32MinidumpWritable::TestUInt32MinidumpWritable(uint32_t value)
|
TestUInt32MinidumpWritable::TestUInt32MinidumpWritable(uint32_t value)
|
||||||
|
@ -98,8 +98,8 @@ MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpSimpleStringDictionary);
|
|||||||
// data).
|
// data).
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(IMAGE_DEBUG_MISC);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(IMAGE_DEBUG_MISC);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_STRING);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MINIDUMP_STRING);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCodeViewRecordPDB20);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(CodeViewRecordPDB20);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpModuleCodeViewRecordPDB70);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(CodeViewRecordPDB70);
|
||||||
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpUTF8String);
|
MINIDUMP_ALLOW_OVERSIZED_DATA(MinidumpUTF8String);
|
||||||
|
|
||||||
// minidump_file_writer_test accesses its variable-sized test streams via a
|
// minidump_file_writer_test accesses its variable-sized test streams via a
|
||||||
@ -142,10 +142,10 @@ const T* TMinidumpWritableAtLocationDescriptor(
|
|||||||
//! specializations ensure that the size given by \a location matches the
|
//! specializations ensure that the size given by \a location matches the
|
||||||
//! size expected of a stream containing the number of elements it claims to
|
//! size expected of a stream containing the number of elements it claims to
|
||||||
//! have.
|
//! have.
|
||||||
//! - With an IMAGE_DEBUG_MISC, MinidumpModuleCodeViewRecordPDB20, or
|
//! - With an IMAGE_DEBUG_MISC, CodeViewRecordPDB20, or CodeViewRecordPDB70
|
||||||
//! MinidumpModuleCodeViewRecordPDB70 template parameter, template
|
//! template parameter, template specializations ensure that the structure
|
||||||
//! specializations ensure that the structure has the expected format
|
//! has the expected format including any magic number and the `NUL`-
|
||||||
//! including any magic number and the `NUL`-terminated string.
|
//! terminated string.
|
||||||
//!
|
//!
|
||||||
//! \param[in] file_contents The contents of the minidump file.
|
//! \param[in] file_contents The contents of the minidump file.
|
||||||
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
|
//! \param[in] location A MINIDUMP_LOCATION_DESCRIPTOR giving the offset within
|
||||||
@ -190,16 +190,14 @@ const MINIDUMP_THREAD_LIST* MinidumpWritableAtLocationDescriptor<
|
|||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCodeViewRecordPDB20*
|
const CodeViewRecordPDB20* MinidumpWritableAtLocationDescriptor<
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB20>(
|
CodeViewRecordPDB20>(const std::string& file_contents,
|
||||||
const std::string& file_contents,
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCodeViewRecordPDB70*
|
const CodeViewRecordPDB70* MinidumpWritableAtLocationDescriptor<
|
||||||
MinidumpWritableAtLocationDescriptor<MinidumpModuleCodeViewRecordPDB70>(
|
CodeViewRecordPDB70>(const std::string& file_contents,
|
||||||
const std::string& file_contents,
|
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
||||||
const MINIDUMP_LOCATION_DESCRIPTOR& location);
|
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
const MinidumpModuleCrashpadInfoList*
|
const MinidumpModuleCrashpadInfoList*
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
'win/cpu_context_win_test.cc',
|
'win/cpu_context_win_test.cc',
|
||||||
'win/exception_snapshot_win_test.cc',
|
'win/exception_snapshot_win_test.cc',
|
||||||
'win/pe_image_annotations_reader_test.cc',
|
'win/pe_image_annotations_reader_test.cc',
|
||||||
|
'win/pe_image_reader_test.cc',
|
||||||
'win/process_reader_win_test.cc',
|
'win/process_reader_win_test.cc',
|
||||||
'win/system_snapshot_win_test.cc',
|
'win/system_snapshot_win_test.cc',
|
||||||
],
|
],
|
||||||
|
@ -148,7 +148,11 @@ ModuleSnapshot::ModuleType ModuleSnapshotWin::GetModuleType() const {
|
|||||||
|
|
||||||
void ModuleSnapshotWin::UUID(crashpad::UUID* uuid) const {
|
void ModuleSnapshotWin::UUID(crashpad::UUID* uuid) const {
|
||||||
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
INITIALIZATION_STATE_DCHECK_VALID(initialized_);
|
||||||
CHECK(false) << "TODO(scottmg)";
|
// TODO(scottmg): Also pass the age and pdbname through to snapshot?
|
||||||
|
DWORD age;
|
||||||
|
std::string pdbname;
|
||||||
|
if (!pe_image_reader_->DebugDirectoryInformation(uuid, &age, &pdbname))
|
||||||
|
*uuid = crashpad::UUID();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> ModuleSnapshotWin::AnnotationsVector() const {
|
std::vector<std::string> ModuleSnapshotWin::AnnotationsVector() const {
|
||||||
|
@ -17,9 +17,11 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
#include "base/memory/scoped_ptr.h"
|
||||||
#include "base/strings/stringprintf.h"
|
#include "base/strings/stringprintf.h"
|
||||||
#include "client/crashpad_info.h"
|
#include "client/crashpad_info.h"
|
||||||
#include "snapshot/win/process_reader_win.h"
|
#include "snapshot/win/process_reader_win.h"
|
||||||
|
#include "util/misc/pdb_structures.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
@ -110,13 +112,70 @@ bool PEImageReader::GetCrashpadInfo(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PEImageReader::GetSectionByName(const std::string& name,
|
bool PEImageReader::DebugDirectoryInformation(UUID* uuid,
|
||||||
IMAGE_SECTION_HEADER* section) const {
|
DWORD* age,
|
||||||
if (name.size() > sizeof(section->Name)) {
|
std::string* pdbname) {
|
||||||
LOG(WARNING) << "supplied section name too long " << name;
|
WinVMAddress nt_headers_address;
|
||||||
|
IMAGE_NT_HEADERS nt_headers;
|
||||||
|
if (!ReadNtHeaders(&nt_headers_address, &nt_headers))
|
||||||
return false;
|
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;
|
||||||
|
for (size_t offset = 0; offset < data_directory.Size;
|
||||||
|
offset += sizeof(debug_directory)) {
|
||||||
|
if (!CheckedReadMemory(Address() + data_directory.VirtualAddress + offset,
|
||||||
|
sizeof(debug_directory),
|
||||||
|
&debug_directory)) {
|
||||||
|
LOG(WARNING) << "could not read data directory";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug_directory.Type != IMAGE_DEBUG_TYPE_CODEVIEW)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (debug_directory.SizeOfData < sizeof(CodeViewRecordPDB70)) {
|
||||||
|
LOG(WARNING) << "CodeView debug entry of unexpected size";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
scoped_ptr<char[]> data(new char[debug_directory.SizeOfData]);
|
||||||
|
if (!CheckedReadMemory(Address() + debug_directory.AddressOfRawData,
|
||||||
|
debug_directory.SizeOfData,
|
||||||
|
data.get())) {
|
||||||
|
LOG(WARNING) << "could not read debug directory";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*reinterpret_cast<DWORD*>(data.get()) !=
|
||||||
|
CodeViewRecordPDB70::kSignature) {
|
||||||
|
// TODO(scottmg): Consider supporting other record types, see
|
||||||
|
// https://code.google.com/p/crashpad/issues/detail?id=47.
|
||||||
|
LOG(WARNING) << "encountered non-7.0 CodeView debug record";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
CodeViewRecordPDB70* codeview =
|
||||||
|
reinterpret_cast<CodeViewRecordPDB70*>(data.get());
|
||||||
|
*uuid = codeview->uuid;
|
||||||
|
*age = codeview->age;
|
||||||
|
// This is a NUL-terminated string encoded in the codepage of the system
|
||||||
|
// where the binary was linked. We have no idea what that was, so we just
|
||||||
|
// assume ASCII.
|
||||||
|
*pdbname = std::string(reinterpret_cast<char*>(&codeview->pdb_name[0]));
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(scottmg): This needs to be made cross-bitness supporting.
|
||||||
|
bool PEImageReader::ReadNtHeaders(WinVMAddress* nt_headers_address,
|
||||||
|
IMAGE_NT_HEADERS* nt_headers) const {
|
||||||
IMAGE_DOS_HEADER dos_header;
|
IMAGE_DOS_HEADER dos_header;
|
||||||
if (!CheckedReadMemory(Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) {
|
if (!CheckedReadMemory(Address(), sizeof(IMAGE_DOS_HEADER), &dos_header)) {
|
||||||
LOG(WARNING) << "could not read dos header of " << module_name_;
|
LOG(WARNING) << "could not read dos header of " << module_name_;
|
||||||
@ -128,20 +187,33 @@ bool PEImageReader::GetSectionByName(const std::string& name,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(scottmg): This is reading a same-bitness sized structure.
|
*nt_headers_address = Address() + dos_header.e_lfanew;
|
||||||
IMAGE_NT_HEADERS nt_headers;
|
|
||||||
WinVMAddress nt_headers_address = Address() + dos_header.e_lfanew;
|
|
||||||
if (!CheckedReadMemory(
|
if (!CheckedReadMemory(
|
||||||
nt_headers_address, sizeof(IMAGE_NT_HEADERS), &nt_headers)) {
|
*nt_headers_address, sizeof(IMAGE_NT_HEADERS), nt_headers)) {
|
||||||
LOG(WARNING) << "could not read nt headers of " << module_name_;
|
LOG(WARNING) << "could not read nt headers of " << module_name_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nt_headers.Signature != IMAGE_NT_SIGNATURE) {
|
if (nt_headers->Signature != IMAGE_NT_SIGNATURE) {
|
||||||
LOG(WARNING) << "invalid signature in nt headers of " << module_name_;
|
LOG(WARNING) << "invalid signature in nt headers of " << module_name_;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PEImageReader::GetSectionByName(const std::string& name,
|
||||||
|
IMAGE_SECTION_HEADER* section) const {
|
||||||
|
if (name.size() > sizeof(section->Name)) {
|
||||||
|
LOG(WARNING) << "supplied section name too long " << name;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
WinVMAddress nt_headers_address;
|
||||||
|
IMAGE_NT_HEADERS nt_headers;
|
||||||
|
if (!ReadNtHeaders(&nt_headers_address, &nt_headers))
|
||||||
|
return false;
|
||||||
|
|
||||||
WinVMAddress first_section_address =
|
WinVMAddress first_section_address =
|
||||||
nt_headers_address + offsetof(IMAGE_NT_HEADERS, OptionalHeader) +
|
nt_headers_address + offsetof(IMAGE_NT_HEADERS, OptionalHeader) +
|
||||||
nt_headers.FileHeader.SizeOfOptionalHeader;
|
nt_headers.FileHeader.SizeOfOptionalHeader;
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "util/misc/initialization_state_dcheck.h"
|
#include "util/misc/initialization_state_dcheck.h"
|
||||||
|
#include "util/misc/uuid.h"
|
||||||
#include "util/win/address_types.h"
|
#include "util/win/address_types.h"
|
||||||
#include "util/win/checked_win_address_range.h"
|
#include "util/win/checked_win_address_range.h"
|
||||||
|
|
||||||
@ -93,7 +94,21 @@ class PEImageReader {
|
|||||||
//! messages. Other failures will result in messages being logged.
|
//! messages. Other failures will result in messages being logged.
|
||||||
bool GetCrashpadInfo(process_types::CrashpadInfo* crashpad_info) const;
|
bool GetCrashpadInfo(process_types::CrashpadInfo* crashpad_info) const;
|
||||||
|
|
||||||
|
//! \brief Obtains information from the module's debug directory, if any.
|
||||||
|
//!
|
||||||
|
//! \param[out] uuid The unique identifier of the executable/PDB.
|
||||||
|
//! \param[out] age The age field for the pdb (the number of times it's been
|
||||||
|
//! relinked).
|
||||||
|
//! \param[out] pdbname Name of the pdb file.
|
||||||
|
//! \return `true` on success, or `false` if the module has no debug directory
|
||||||
|
//! entry.
|
||||||
|
bool DebugDirectoryInformation(UUID* uuid, DWORD* age, std::string* pdbname);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
//! \brief Reads the `IMAGE_NT_HEADERS` from the beginning of the image.
|
||||||
|
bool ReadNtHeaders(WinVMAddress* nt_header_address,
|
||||||
|
IMAGE_NT_HEADERS* nt_headers) const;
|
||||||
|
|
||||||
//! \brief Finds a given section by name in the image.
|
//! \brief Finds a given section by name in the image.
|
||||||
bool GetSectionByName(const std::string& name,
|
bool GetSectionByName(const std::string& name,
|
||||||
IMAGE_SECTION_HEADER* section) const;
|
IMAGE_SECTION_HEADER* section) const;
|
||||||
|
54
snapshot/win/pe_image_reader_test.cc
Normal file
54
snapshot/win/pe_image_reader_test.cc
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
// 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"
|
||||||
|
|
||||||
|
#include <psapi.h>
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "snapshot/win/process_reader_win.h"
|
||||||
|
|
||||||
|
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
namespace test {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
TEST(PEImageReader, DebugDirectory) {
|
||||||
|
PEImageReader pe_image_reader;
|
||||||
|
ProcessReaderWin process_reader;
|
||||||
|
ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess()));
|
||||||
|
HMODULE self = reinterpret_cast<HMODULE>(&__ImageBase);
|
||||||
|
MODULEINFO module_info;
|
||||||
|
ASSERT_TRUE(GetModuleInformation(
|
||||||
|
GetCurrentProcess(), self, &module_info, sizeof(module_info)));
|
||||||
|
EXPECT_EQ(self, module_info.lpBaseOfDll);
|
||||||
|
EXPECT_TRUE(pe_image_reader.Initialize(&process_reader,
|
||||||
|
reinterpret_cast<WinVMAddress>(self),
|
||||||
|
module_info.SizeOfImage,
|
||||||
|
"self"));
|
||||||
|
UUID uuid;
|
||||||
|
DWORD age;
|
||||||
|
std::string pdbname;
|
||||||
|
EXPECT_TRUE(pe_image_reader.DebugDirectoryInformation(&uuid, &age, &pdbname));
|
||||||
|
EXPECT_NE(-1, pdbname.find("crashpad_snapshot_test"));
|
||||||
|
const std::string suffix(".pdb");
|
||||||
|
EXPECT_EQ(
|
||||||
|
0,
|
||||||
|
pdbname.compare(pdbname.size() - suffix.size(), suffix.size(), suffix));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace test
|
||||||
|
} // namespace crashpad
|
22
util/misc/pdb_structures.cc
Normal file
22
util/misc/pdb_structures.cc
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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 "util/misc/pdb_structures.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
const uint32_t CodeViewRecordPDB20::kSignature;
|
||||||
|
const uint32_t CodeViewRecordPDB70::kSignature;
|
||||||
|
|
||||||
|
} // namespace crashpad
|
131
util/misc/pdb_structures.h
Normal file
131
util/misc/pdb_structures.h
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef CRASHPAD_UTIL_MISC_PDB_STRUCTURES_H_
|
||||||
|
#define CRASHPAD_UTIL_MISC_PDB_STRUCTURES_H_
|
||||||
|
|
||||||
|
#include "util/misc/uuid.h"
|
||||||
|
|
||||||
|
namespace crashpad {
|
||||||
|
|
||||||
|
//! \brief A CodeView record linking to a `.pdb` 2.0 file.
|
||||||
|
//!
|
||||||
|
//! This format provides an indirect link to debugging data by referencing an
|
||||||
|
//! external `.pdb` file by its name, timestamp, and age. This structure may be
|
||||||
|
//! pointed to by MINIDUMP_MODULE::CvRecord. It has been superseded by
|
||||||
|
//! CodeViewRecordPDB70.
|
||||||
|
//!
|
||||||
|
//! For more information about this structure and format, see <a
|
||||||
|
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
||||||
|
//! Debug Information</a>, PDB Files, and <a
|
||||||
|
//! href="http://undocumented.rawol.com/sbs-w2k-1-windows-2000-debugging-support.pdf#page=63">Undocumented
|
||||||
|
//! Windows 2000 Secrets</a>, Windows 2000 Debugging Support/Microsoft Symbol
|
||||||
|
//! File Internals/CodeView Subsections.
|
||||||
|
//!
|
||||||
|
//! \sa IMAGE_DEBUG_MISC
|
||||||
|
struct CodeViewRecordPDB20 {
|
||||||
|
//! \brief The magic number identifying this structure version, stored in
|
||||||
|
//! #signature.
|
||||||
|
//!
|
||||||
|
//! In a hex dump, this will appear as “NB10” when produced by a little-endian
|
||||||
|
//! machine.
|
||||||
|
static const uint32_t kSignature = '01BN';
|
||||||
|
|
||||||
|
//! \brief The magic number identifying this structure version, the value of
|
||||||
|
//! #kSignature.
|
||||||
|
uint32_t signature;
|
||||||
|
|
||||||
|
//! \brief The offset to CodeView data.
|
||||||
|
//!
|
||||||
|
//! In this structure, this field always has the value `0` because no CodeView
|
||||||
|
//! data is present, there is only a link to CodeView data stored in an
|
||||||
|
//! external file.
|
||||||
|
uint32_t offset;
|
||||||
|
|
||||||
|
//! \brief The time that the `.pdb` file was created, in `time_t` format, the
|
||||||
|
//! number of seconds since the POSIX epoch.
|
||||||
|
uint32_t timestamp;
|
||||||
|
|
||||||
|
//! \brief The revision of the `.pdb` file.
|
||||||
|
//!
|
||||||
|
//! A `.pdb` file’s age indicates incremental changes to it. When a `.pdb`
|
||||||
|
//! file is created, it has age `1`, and subsequent updates increase this
|
||||||
|
//! value.
|
||||||
|
uint32_t age;
|
||||||
|
|
||||||
|
//! \brief The path or file name of the `.pdb` file associated with the
|
||||||
|
//! module.
|
||||||
|
//!
|
||||||
|
//! This is a NUL-terminated string. On Windows, it will be encoded in the
|
||||||
|
//! code page of the system that linked the module. On other operating
|
||||||
|
//! systems, UTF-8 may be used.
|
||||||
|
uint8_t pdb_name[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
//! \brief A CodeView record linking to a `.pdb` 7.0 file.
|
||||||
|
//!
|
||||||
|
//! This format provides an indirect link to debugging data by referencing an
|
||||||
|
//! external `.pdb` file by its name, %UUID, and age. This structure may be
|
||||||
|
//! pointed to by MINIDUMP_MODULE::CvRecord.
|
||||||
|
//!
|
||||||
|
//! For more information about this structure and format, see <a
|
||||||
|
//! href="http://www.debuginfo.com/articles/debuginfomatch.html#pdbfiles">Matching
|
||||||
|
//! Debug Information</a>, PDB Files.
|
||||||
|
//!
|
||||||
|
//! \sa CodeViewRecordPDB20
|
||||||
|
//! \sa IMAGE_DEBUG_MISC
|
||||||
|
struct CodeViewRecordPDB70 {
|
||||||
|
// UUID has a constructor, which makes it non-POD, which makes this structure
|
||||||
|
// non-POD. In order for the default constructor to zero-initialize other
|
||||||
|
// members, an explicit constructor must be provided.
|
||||||
|
CodeViewRecordPDB70()
|
||||||
|
: signature(),
|
||||||
|
uuid(),
|
||||||
|
age(),
|
||||||
|
pdb_name() {
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \brief The magic number identifying this structure version, stored in
|
||||||
|
//! #signature.
|
||||||
|
//!
|
||||||
|
//! In a hex dump, this will appear as “RSDS” when produced by a little-endian
|
||||||
|
//! machine.
|
||||||
|
static const uint32_t kSignature = 'SDSR';
|
||||||
|
|
||||||
|
//! \brief The magic number identifying this structure version, the value of
|
||||||
|
//! #kSignature.
|
||||||
|
uint32_t signature;
|
||||||
|
|
||||||
|
//! \brief The `.pdb` file’s unique identifier.
|
||||||
|
UUID uuid;
|
||||||
|
|
||||||
|
//! \brief The revision of the `.pdb` file.
|
||||||
|
//!
|
||||||
|
//! A `.pdb` file’s age indicates incremental changes to it. When a `.pdb`
|
||||||
|
//! file is created, it has age `1`, and subsequent updates increase this
|
||||||
|
//! value.
|
||||||
|
uint32_t age;
|
||||||
|
|
||||||
|
//! \brief The path or file name of the `.pdb` file associated with the
|
||||||
|
//! module.
|
||||||
|
//!
|
||||||
|
//! This is a NUL-terminated string. On Windows, it will be encoded in the
|
||||||
|
//! code page of the system that linked the module. On other operating
|
||||||
|
//! systems, UTF-8 may be used.
|
||||||
|
uint8_t pdb_name[1];
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace crashpad
|
||||||
|
|
||||||
|
#endif // CRASHPAD_UTIL_MISC_PDB_STRUCTURES_H_
|
@ -91,6 +91,8 @@
|
|||||||
'misc/initialization_state.h',
|
'misc/initialization_state.h',
|
||||||
'misc/initialization_state_dcheck.cc',
|
'misc/initialization_state_dcheck.cc',
|
||||||
'misc/initialization_state_dcheck.h',
|
'misc/initialization_state_dcheck.h',
|
||||||
|
'misc/pdb_structures.cc',
|
||||||
|
'misc/pdb_structures.h',
|
||||||
'misc/scoped_forbid_return.cc',
|
'misc/scoped_forbid_return.cc',
|
||||||
'misc/scoped_forbid_return.h',
|
'misc/scoped_forbid_return.h',
|
||||||
'misc/symbolic_constants_common.h',
|
'misc/symbolic_constants_common.h',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user