kicad/thirdparty/sentry-native/external/crashpad/minidump/minidump_module_writer.h

393 lines
14 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 2014 The Crashpad Authors
//
// 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_MINIDUMP_MINIDUMP_MODULE_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_MODULE_WRITER_H_
#include <windows.h>
#include <dbghelp.h>
#include <stdint.h>
#include <sys/types.h>
#include <time.h>
#include <memory>
#include <string>
#include <vector>
#include "minidump/minidump_extensions.h"
#include "minidump/minidump_stream_writer.h"
#include "minidump/minidump_writable.h"
namespace crashpad {
class ModuleSnapshot;
namespace internal {
class MinidumpUTF16StringWriter;
} // namespace internal
//! \brief The base class for writers of CodeView records referenced by
//! MINIDUMP_MODULE::CvRecord in minidump files.
class MinidumpModuleCodeViewRecordWriter : public internal::MinidumpWritable {
public:
MinidumpModuleCodeViewRecordWriter(
const MinidumpModuleCodeViewRecordWriter&) = delete;
MinidumpModuleCodeViewRecordWriter& operator=(
const MinidumpModuleCodeViewRecordWriter&) = delete;
~MinidumpModuleCodeViewRecordWriter() override;
protected:
MinidumpModuleCodeViewRecordWriter() : MinidumpWritable() {}
};
namespace internal {
//! \brief The base class for writers of CodeView records that serve as links to
//! `.pdb` (program database) files.
template <typename CodeViewRecordType>
class MinidumpModuleCodeViewRecordPDBLinkWriter
: public MinidumpModuleCodeViewRecordWriter {
public:
MinidumpModuleCodeViewRecordPDBLinkWriter(
const MinidumpModuleCodeViewRecordPDBLinkWriter&) = delete;
MinidumpModuleCodeViewRecordPDBLinkWriter& operator=(
const MinidumpModuleCodeViewRecordPDBLinkWriter&) = delete;
//! \brief Sets the name of the `.pdb` file being linked to.
void SetPDBName(const std::string& pdb_name) { pdb_name_ = pdb_name; }
protected:
MinidumpModuleCodeViewRecordPDBLinkWriter();
~MinidumpModuleCodeViewRecordPDBLinkWriter() override;
// MinidumpWritable:
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
//! \brief Returns a pointer to the raw CodeView records data.
//!
//! Subclasses can use this to set fields in their codeview records other than
//! the `pdb_name` field.
CodeViewRecordType* codeview_record() { return &codeview_record_; }
private:
CodeViewRecordType codeview_record_;
std::string pdb_name_;
};
} // namespace internal
//! \brief The writer for a CodeViewRecordPDB20 object in a minidump file.
//!
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer or
//! MinidumpModuleCodeViewRecordBuildIDWriter instead.
class MinidumpModuleCodeViewRecordPDB20Writer final
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB20> {
public:
MinidumpModuleCodeViewRecordPDB20Writer()
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB20>() {}
MinidumpModuleCodeViewRecordPDB20Writer(
const MinidumpModuleCodeViewRecordPDB20Writer&) = delete;
MinidumpModuleCodeViewRecordPDB20Writer& operator=(
const MinidumpModuleCodeViewRecordPDB20Writer&) = delete;
~MinidumpModuleCodeViewRecordPDB20Writer() override;
//! \brief Sets CodeViewRecordPDB20::timestamp and CodeViewRecordPDB20::age.
void SetTimestampAndAge(time_t timestamp, uint32_t age);
};
//! \brief The writer for a CodeViewRecordPDB70 object in a minidump file.
class MinidumpModuleCodeViewRecordPDB70Writer final
: public internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB70> {
public:
MinidumpModuleCodeViewRecordPDB70Writer()
: internal::MinidumpModuleCodeViewRecordPDBLinkWriter<
CodeViewRecordPDB70>() {}
MinidumpModuleCodeViewRecordPDB70Writer(
const MinidumpModuleCodeViewRecordPDB70Writer&) = delete;
MinidumpModuleCodeViewRecordPDB70Writer& operator=(
const MinidumpModuleCodeViewRecordPDB70Writer&) = delete;
~MinidumpModuleCodeViewRecordPDB70Writer() override;
//! \brief Initializes the CodeViewRecordPDB70 based on \a module_snapshot.
//!
//! \param[in] module_snapshot The module snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
//! \brief Sets CodeViewRecordPDB70::uuid and CodeViewRecordPDB70::age.
void SetUUIDAndAge(const UUID& uuid, uint32_t age) {
codeview_record()->uuid = uuid;
codeview_record()->age = age;
}
};
//! \brief The writer for a CodeViewRecordBuildID object in a minidump file.
class MinidumpModuleCodeViewRecordBuildIDWriter final
: public MinidumpModuleCodeViewRecordWriter {
public:
MinidumpModuleCodeViewRecordBuildIDWriter();
MinidumpModuleCodeViewRecordBuildIDWriter(
const MinidumpModuleCodeViewRecordBuildIDWriter&) = delete;
MinidumpModuleCodeViewRecordBuildIDWriter& operator=(
const MinidumpModuleCodeViewRecordBuildIDWriter&) = delete;
~MinidumpModuleCodeViewRecordBuildIDWriter() override;
//! \brief Sets the build ID used for symbol lookup.
void SetBuildID(const std::vector<uint8_t>& build_id);
private:
// MinidumpWritable:
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
std::vector<uint8_t> build_id_;
};
//! \brief The writer for an IMAGE_DEBUG_MISC object in a minidump file.
//!
//! Most users will want MinidumpModuleCodeViewRecordPDB70Writer instead.
class MinidumpModuleMiscDebugRecordWriter final
: public internal::MinidumpWritable {
public:
MinidumpModuleMiscDebugRecordWriter();
MinidumpModuleMiscDebugRecordWriter(
const MinidumpModuleMiscDebugRecordWriter&) = delete;
MinidumpModuleMiscDebugRecordWriter& operator=(
const MinidumpModuleMiscDebugRecordWriter&) = delete;
~MinidumpModuleMiscDebugRecordWriter() override;
//! \brief Sets IMAGE_DEBUG_MISC::DataType.
void SetDataType(uint32_t data_type) {
image_debug_misc_.DataType = data_type;
}
//! \brief Sets IMAGE_DEBUG_MISC::Data, IMAGE_DEBUG_MISC::Length, and
//! IMAGE_DEBUG_MISC::Unicode.
//!
//! If \a utf16 is `true`, \a data will be treated as UTF-8 data and will be
//! converted to UTF-16, and IMAGE_DEBUG_MISC::Unicode will be set to `1`.
//! Otherwise, \a data will be used as-is and IMAGE_DEBUG_MISC::Unicode will
//! be set to `0`.
void SetData(const std::string& data, bool utf16);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
IMAGE_DEBUG_MISC image_debug_misc_;
std::string data_;
std::u16string data_utf16_;
};
//! \brief The writer for a MINIDUMP_MODULE object in a minidump file.
//!
//! Because MINIDUMP_MODULE objects only appear as elements of
//! MINIDUMP_MODULE_LIST objects, this class does not write any data on its own.
//! It makes its MINIDUMP_MODULE data available to its MinidumpModuleListWriter
//! parent, which writes it as part of a MINIDUMP_MODULE_LIST.
class MinidumpModuleWriter final : public internal::MinidumpWritable {
public:
MinidumpModuleWriter();
MinidumpModuleWriter(const MinidumpModuleWriter&) = delete;
MinidumpModuleWriter& operator=(const MinidumpModuleWriter&) = delete;
~MinidumpModuleWriter() override;
//! \brief Initializes the MINIDUMP_MODULE based on \a module_snapshot.
//!
//! \param[in] module_snapshot The module snapshot to use as source data.
//!
//! \note Valid in #kStateMutable. No mutator methods may be called before
//! this method, and it is not normally necessary to call any mutator
//! methods after this method.
void InitializeFromSnapshot(const ModuleSnapshot* module_snapshot);
//! \brief Returns a MINIDUMP_MODULE referencing this objects data.
//!
//! This method is expected to be called by a MinidumpModuleListWriter in
//! order to obtain a MINIDUMP_MODULE to include in its list.
//!
//! \note Valid in #kStateWritable.
const MINIDUMP_MODULE* MinidumpModule() const;
//! \brief Arranges for MINIDUMP_MODULE::ModuleNameRva to point to a
//! MINIDUMP_STRING containing \a name.
//!
//! A name is required in all MINIDUMP_MODULE objects.
//!
//! \note Valid in #kStateMutable.
void SetName(const std::string& name);
//! \brief Arranges for MINIDUMP_MODULE::CvRecord to point to a CodeView
//! record to be written by \a codeview_record.
//!
//! This object takes ownership of \a codeview_record and becomes its parent
//! in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetCodeViewRecord(
std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record);
//! \brief Arranges for MINIDUMP_MODULE::MiscRecord to point to an
//! IMAGE_DEBUG_MISC object to be written by \a misc_debug_record.
//!
//! This object takes ownership of \a misc_debug_record and becomes its parent
//! in the overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void SetMiscDebugRecord(
std::unique_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record);
//! \brief Sets IMAGE_DEBUG_MISC::BaseOfImage.
void SetImageBaseAddress(uint64_t image_base_address) {
module_.BaseOfImage = image_base_address;
}
//! \brief Sets IMAGE_DEBUG_MISC::SizeOfImage.
void SetImageSize(uint32_t image_size) { module_.SizeOfImage = image_size; }
//! \brief Sets IMAGE_DEBUG_MISC::CheckSum.
void SetChecksum(uint32_t checksum) { module_.CheckSum = checksum; }
//! \brief Sets IMAGE_DEBUG_MISC::TimeDateStamp.
//!
//! \note Valid in #kStateMutable.
void SetTimestamp(time_t timestamp);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileVersionMS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileVersionMS" and \ref
//! VS_FIXEDFILEINFO::dwFileVersionLS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileVersionLS".
//!
//! \note Valid in #kStateMutable.
void SetFileVersion(uint16_t version_0,
uint16_t version_1,
uint16_t version_2,
uint16_t version_3);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwProductVersionMS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwProductVersionMS" and \ref
//! VS_FIXEDFILEINFO::dwProductVersionLS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwProductVersionLS".
//!
//! \note Valid in #kStateMutable.
void SetProductVersion(uint16_t version_0,
uint16_t version_1,
uint16_t version_2,
uint16_t version_3);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileFlags
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileFlags" and \ref
//! VS_FIXEDFILEINFO::dwFileFlagsMask
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileFlagsMask".
//!
//! \note Valid in #kStateMutable.
void SetFileFlagsAndMask(uint32_t file_flags, uint32_t file_flags_mask);
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileOS
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileOS".
void SetFileOS(uint32_t file_os) { module_.VersionInfo.dwFileOS = file_os; }
//! \brief Sets \ref VS_FIXEDFILEINFO::dwFileType
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileType" and \ref
//! VS_FIXEDFILEINFO::dwFileSubtype
//! "IMAGE_DEBUG_MISC::VersionInfo::dwFileSubtype".
void SetFileTypeAndSubtype(uint32_t file_type, uint32_t file_subtype) {
module_.VersionInfo.dwFileType = file_type;
module_.VersionInfo.dwFileSubtype = file_subtype;
}
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
private:
MINIDUMP_MODULE module_;
std::unique_ptr<internal::MinidumpUTF16StringWriter> name_;
std::unique_ptr<MinidumpModuleCodeViewRecordWriter> codeview_record_;
std::unique_ptr<MinidumpModuleMiscDebugRecordWriter> misc_debug_record_;
};
//! \brief The writer for a MINIDUMP_MODULE_LIST stream in a minidump file,
//! containing a list of MINIDUMP_MODULE objects.
class MinidumpModuleListWriter final : public internal::MinidumpStreamWriter {
public:
MinidumpModuleListWriter();
MinidumpModuleListWriter(const MinidumpModuleListWriter&) = delete;
MinidumpModuleListWriter& operator=(const MinidumpModuleListWriter&) = delete;
~MinidumpModuleListWriter() override;
//! \brief Adds an initialized MINIDUMP_MODULE for each module in \a
//! module_snapshots to the MINIDUMP_MODULE_LIST.
//!
//! \param[in] module_snapshots The module snapshots to use as source data.
//!
//! \note Valid in #kStateMutable. AddModule() may not be called before this
//! method, and it is not normally necessary to call AddModule() after
//! this method.
void InitializeFromSnapshot(
const std::vector<const ModuleSnapshot*>& module_snapshots);
//! \brief Adds a MinidumpModuleWriter to the MINIDUMP_MODULE_LIST.
//!
//! This object takes ownership of \a module and becomes its parent in the
//! overall tree of internal::MinidumpWritable objects.
//!
//! \note Valid in #kStateMutable.
void AddModule(std::unique_ptr<MinidumpModuleWriter> module);
protected:
// MinidumpWritable:
bool Freeze() override;
size_t SizeOfObject() override;
std::vector<MinidumpWritable*> Children() override;
bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpStreamWriter:
MinidumpStreamType StreamType() const override;
private:
std::vector<std::unique_ptr<MinidumpModuleWriter>> modules_;
MINIDUMP_MODULE_LIST module_list_base_;
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_MODULE_WRITER_H_