Add MinidumpContext (X86 and AMD64 variants) and their writers.

These are fairly simple classes and it’s not valuable to test them
individually. They will be tested as part of MinidumpThreadWriter and
MinidumpExceptionWriter.

R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/593583004
This commit is contained in:
Mark Mentovai 2014-09-24 13:34:45 -04:00
Родитель 0d59a76735
Коммит cb2288d174
4 изменённых файлов: 558 добавлений и 0 удалений

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

@ -29,6 +29,9 @@
'..',
],
'sources': [
'minidump_context.h',
'minidump_context_writer.cc',
'minidump_context_writer.h',
'minidump_extensions.cc',
'minidump_extensions.h',
'minidump_file_writer.cc',

363
minidump/minidump_context.h Normal file
Просмотреть файл

@ -0,0 +1,363 @@
// Copyright 2014 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_MINIDUMP_MINIDUMP_CONTEXT_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_
#include <stdint.h>
#include "util/numeric/int128.h"
namespace crashpad {
//! \brief Architecture-independent flags for `context_flags` fields in Minidump
//! context structures.
//
// http://zachsaw.blogspot.com/2010/11/wow64-bug-getthreadcontext-may-return.html#c5639760895973344002
enum MinidumpContextFlags : uint32_t {
//! \brief The thread was executing a trap handler in kernel mode
//! (`CONTEXT_EXCEPTION_ACTIVE`).
//!
//! If this bit is set, it indicates that the context is from a thread that
//! was executing a trap handler in the kernel. This bit is only valid when
//! ::kMinidumpContextExceptionReporting is also set. This bit is only used on
//! Windows.
kMinidumpContextExceptionActive = 0x08000000,
//! \brief The thread was executing a system call in kernel mode
//! (`CONTEXT_SERVICE_ACTIVE`).
//!
//! If this bit is set, it indicates that the context is from a thread that
//! was executing a system call in the kernel. This bit is only valid when
//! ::kMinidumpContextExceptionReporting is also set. This bit is only used on
//! Windows.
kMinidumpContextServiceActive = 0x10000000,
//! \brief Kernel-mode state reporting is desired
//! (`CONTEXT_EXCEPTION_REQUEST`).
//!
//! This bit is not used in context structures containing snapshots of thread
//! CPU context. It used when calling `GetThreadContext()` on Windows to
//! specify that kernel-mode state reporting
//! (::kMinidumpContextExceptionReporting) is desired in the returned context
//! structure.
kMinidumpContextExceptionRequest = 0x40000000,
//! \brief Kernel-mode state reporting is provided
//! (`CONTEXT_EXCEPTION_REPORTING`).
//!
//! If this bit is set, it indicates that the bits indicating how the thread
//! had entered kernel mode (::kMinidumpContextExceptionActive and
//! and ::kMinidumpContextServiceActive) are valid. This bit is only used on
//! Windows.
kMinidumpContextExceptionReporting = 0x80000000,
};
//! \brief 32-bit x86-specifc flags for MinidumpContextX86::context_flags.
enum MinidumpContextX86Flags : uint32_t {
//! \brief Identifies the context structure as 32-bit x86. This is the same as
//! `CONTEXT_i386` and `CONTEXT_i486` on Windows for this architecture.
kMinidumpContextX86 = 0x00010000,
//! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`).
//!
//! The `ebp`, `eip`, `cs`, `eflags`, `esp`, and `ss` fields are valid.
kMinidumpContextX86Control = kMinidumpContextX86 | 0x00000001,
//! \brief Indicates the validity of non-control integer registers
//! (`CONTEXT_INTEGER`).
//!
//! The `edi`, `esi`, `ebx`, `edx`, `ecx, and `eax` fields are valid.
kMinidumpContextX86Integer = kMinidumpContextX86 | 0x00000002,
//! \brief Indicates the validity of non-control segment registers
//! (`CONTEXT_SEGMENTS`).
//!
//! The `gs`, `fs`, `es`, and `ds` fields are valid.
kMinidumpContextX86Segment = kMinidumpContextX86 | 0x00000004,
//! \brief Indicates the validity of floating-point state
//! (`CONTEXT_FLOATING_POINT`).
//!
//! The `float_save` field is valid.
kMinidumpContextX86FloatingPoint = kMinidumpContextX86 | 0x00000008,
//! \brief Indicates the validity of debug registers
//! (`CONTEXT_DEBUG_REGISTERS`).
//!
//! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid.
kMinidumpContextX86Debug = kMinidumpContextX86 | 0x00000010,
//! \brief Indicates the validity of extended registers in `fxsave` format
//! (`CONTEXT_EXTENDED_REGISTERS`).
//!
//! The `extended_registers` field is valid and contains `fxsave` data.
kMinidumpContextX86Extended = kMinidumpContextX86 | 0x00000020,
//! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`).
//!
//! The context contains `xsave` data. This is used with an extended context
//! structure not currently defined here.
kMinidumpContextX86Xstate = kMinidumpContextX86 | 0x00000040,
//! \brief Indicates the validity of control, integer, and segment registers.
kMinidumpContextX86Full = kMinidumpContextX86Control |
kMinidumpContextX86Integer |
kMinidumpContextX86Segment,
//! \brief Indicates the validity of all registers except `xsave` data.
kMinidumpContextX86All = kMinidumpContextX86Full |
kMinidumpContextX86FloatingPoint |
kMinidumpContextX86Debug |
kMinidumpContextX86Extended,
};
//! \brief A 32-bit x86 CPU context (register state) carried in a minidump file.
//!
//! This is analogous to the `CONTEXT` structure on Windows when targeting
//! 32-bit x86. This structure is used instead of `CONTEXT` to make it available
//! when targeting other architectures.
struct MinidumpContextX86 {
//! \brief A bitfield composed of values of #MinidumpContextFlags and
//! #MinidumpContextX86Flags.
//!
//! This field identifies the context structure as a 32-bit x86 CPU context,
//! and indicates which other fields in the structure are valid.
uint32_t context_flags;
uint32_t dr0;
uint32_t dr1;
uint32_t dr2;
uint32_t dr3;
uint32_t dr6;
uint32_t dr7;
struct {
uint32_t control_word;
uint32_t status_word;
uint32_t tag_word;
uint32_t error_offset;
uint32_t error_selector;
uint32_t data_offset;
uint32_t data_selector;
uint8_t register_area[80];
uint32_t spare_0;
} float_save;
uint32_t gs;
uint32_t fs;
uint32_t es;
uint32_t ds;
uint32_t edi;
uint32_t esi;
uint32_t ebx;
uint32_t edx;
uint32_t ecx;
uint32_t eax;
uint32_t ebp;
uint32_t eip;
uint32_t cs;
uint32_t eflags;
uint32_t esp;
uint32_t ss;
uint8_t extended_registers[512];
};
//! \brief x86_64-specifc flags for MinidumpContextAMD64::context_flags.
enum MinidumpContextAMD64Flags : uint32_t {
//! \brief Identifies the context structure as x86_64. This is the same as
//! `CONTEXT_AMD64` on Windows for this architecture.
kMinidumpContextAMD64 = 0x00100000,
//! \brief Indicates the validity of control registers (`CONTEXT_CONTROL`).
//!
//! The `cs`, `ss`, `eflags`, `rsp`, and `rip` fields are valid.
kMinidumpContextAMD64Control = kMinidumpContextAMD64 | 0x00000001,
//! \brief Indicates the validity of non-control integer registers
//! (`CONTEXT_INTEGER`).
//!
//! The `rax`, `rcx`, `rdx`, `rbx`, `rbp`, `rsi`, `rdi`, and `r8` through
//! `r15` fields are valid.
kMinidumpContextAMD64Integer = kMinidumpContextAMD64 | 0x00000002,
//! \brief Indicates the validity of non-control segment registers
//! (`CONTEXT_SEGMENTS`).
//!
//! The `ds`, `es`, `fs`, and `gs` fields are valid.
kMinidumpContextAMD64Segment = kMinidumpContextAMD64 | 0x00000004,
//! \brief Indicates the validity of floating-point state
//! (`CONTEXT_FLOATING_POINT`).
//!
//! The `xmm0` through `xmm15` fields are valid.
kMinidumpContextAMD64FloatingPoint = kMinidumpContextAMD64 | 0x00000008,
//! \brief Indicates the validity of debug registers
//! (`CONTEXT_DEBUG_REGISTERS`).
//!
//! The `dr0` through `dr3`, `dr6`, and `dr7` fields are valid.
kMinidumpContextAMD64Debug = kMinidumpContextAMD64 | 0x00000010,
//! \brief Indicates the validity of `xsave` data (`CONTEXT_XSTATE`).
//!
//! The context contains `xsave` data. This is used with an extended context
//! structure not currently defined here.
kMinidumpContextX86Xstate = kMinidumpContextAMD64 | 0x00000040,
//! \brief Indicates the validity of control, integer, and segment registers.
kMinidumpContextAMD64Full = kMinidumpContextAMD64Control |
kMinidumpContextAMD64Integer |
kMinidumpContextAMD64Segment,
//! \brief Indicates the validity of all registers except `xsave` data.
kMinidumpContextAMD64All = kMinidumpContextAMD64Full |
kMinidumpContextAMD64FloatingPoint |
kMinidumpContextAMD64Debug,
};
//! \brief An x86_64 (AMD64) CPU context (register state) carried in a minidump
//! file.
//!
//! This is analogous to the `CONTEXT` structure on Windows when targeting
//! x86_64. This structure is used instead of `CONTEXT` to make it available
//! when targeting other architectures.
struct __attribute__((aligned(16))) MinidumpContextAMD64 {
//! \brief Register parameter home address.
//!
//! On Windows, this field may contain the “home” address (on-stack, in the
//! shadow area) of a parameter passed by register. This field is present for
//! convenience but is not necessarily populated, even if a corresponding
//! parameter was passed by register.
//!
//! \{
uint64_t p1_home;
uint64_t p2_home;
uint64_t p3_home;
uint64_t p4_home;
uint64_t p5_home;
uint64_t p6_home;
//! \}
//! \brief A bitfield composed of values of #MinidumpContextFlags and
//! #MinidumpContextAMD64Flags.
//!
//! This field identifies the context structure as an x86_64 CPU context, and
//! indicates which other fields in the structure are valid.
uint32_t context_flags;
uint32_t mx_csr;
uint16_t cs;
uint16_t ds;
uint16_t es;
uint16_t fs;
uint16_t gs;
uint16_t ss;
uint32_t eflags;
uint64_t dr0;
uint64_t dr1;
uint64_t dr2;
uint64_t dr3;
uint64_t dr6;
uint64_t dr7;
uint64_t rax;
uint64_t rcx;
uint64_t rdx;
uint64_t rbx;
uint64_t rsp;
uint64_t rbp;
uint64_t rsi;
uint64_t rdi;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rip;
union {
struct {
uint16_t control_word;
uint16_t status_word;
uint8_t tag_word;
uint8_t reserved_1;
uint16_t error_opcode;
uint32_t error_offset;
uint16_t error_selector;
uint16_t reserved_2;
uint32_t data_offset;
uint16_t data_selector;
uint16_t reserved_3;
uint32_t mx_csr;
uint32_t mx_csr_mask;
uint128_struct float_registers[8];
uint128_struct xmm_registers[16];
uint8_t reserved_4[96];
} float_save;
struct {
uint128_struct header[2];
uint128_struct legacy[8];
uint128_struct xmm0;
uint128_struct xmm1;
uint128_struct xmm2;
uint128_struct xmm3;
uint128_struct xmm4;
uint128_struct xmm5;
uint128_struct xmm6;
uint128_struct xmm7;
uint128_struct xmm8;
uint128_struct xmm9;
uint128_struct xmm10;
uint128_struct xmm11;
uint128_struct xmm12;
uint128_struct xmm13;
uint128_struct xmm14;
uint128_struct xmm15;
};
};
uint128_struct vector_register[26];
uint64_t vector_control;
//! \brief Model-specific debug extension register.
//!
//! See Intel Software Developers Manual, Volume 3B: System Programming, Part
//! 2 (253669-051), 17.4 “Last Branch, Interrupt, and Exception Recording
//! Overview”, and AMD Architecture Programmers Manual, Volume 2:
//! System Programming (24593-3.24), 13.1.6 “Control-Transfer Breakpoint
//! Features”.
//!
//! \{
uint64_t debug_control;
uint64_t last_branch_to_rip;
uint64_t last_branch_from_rip;
uint64_t last_exception_to_rip;
uint64_t last_exception_from_rip;
//! \}
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_H_

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

@ -0,0 +1,77 @@
// Copyright 2014 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 "minidump/minidump_context_writer.h"
#include "base/logging.h"
namespace crashpad {
MinidumpContextWriter::~MinidumpContextWriter() {
}
size_t MinidumpContextWriter::SizeOfObject() {
DCHECK_GE(state(), kStateFrozen);
return ContextSize();
}
MinidumpContextX86Writer::MinidumpContextX86Writer()
: MinidumpContextWriter(), context_() {
context_.context_flags = kMinidumpContextX86;
}
MinidumpContextX86Writer::~MinidumpContextX86Writer() {
}
bool MinidumpContextX86Writer::WriteObject(FileWriterInterface* file_writer) {
DCHECK_EQ(state(), kStateWritable);
return file_writer->Write(&context_, sizeof(context_));
}
size_t MinidumpContextX86Writer::ContextSize() const {
DCHECK_GE(state(), kStateFrozen);
return sizeof(context_);
}
MinidumpContextAMD64Writer::MinidumpContextAMD64Writer()
: MinidumpContextWriter(), context_() {
context_.context_flags = kMinidumpContextAMD64;
}
MinidumpContextAMD64Writer::~MinidumpContextAMD64Writer() {
}
size_t MinidumpContextAMD64Writer::Alignment() {
DCHECK_GE(state(), kStateFrozen);
// Match the alignment of MinidumpContextAMD64.
return 16;
}
bool MinidumpContextAMD64Writer::WriteObject(FileWriterInterface* file_writer) {
DCHECK_EQ(state(), kStateWritable);
return file_writer->Write(&context_, sizeof(context_));
}
size_t MinidumpContextAMD64Writer::ContextSize() const {
DCHECK_GE(state(), kStateFrozen);
return sizeof(context_);
}
} // namespace crashpad

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

@ -0,0 +1,115 @@
// Copyright 2014 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_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
#define CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_
#include <sys/types.h>
#include "base/basictypes.h"
#include "minidump/minidump_context.h"
#include "minidump/minidump_writable.h"
#include "util/file/file_writer.h"
namespace crashpad {
//! \brief The base class for writers of CPU context structures in minidump
//! files.
class MinidumpContextWriter : public internal::MinidumpWritable {
public:
virtual ~MinidumpContextWriter();
protected:
MinidumpContextWriter() : MinidumpWritable() {}
//! \brief Returns the size of the context structure that this object will
//! write.
//!
//! \note This method will only be called in #kStateFrozen or a subsequent
//! state.
virtual size_t ContextSize() const = 0;
// MinidumpWritable:
virtual size_t SizeOfObject() override final;
private:
DISALLOW_COPY_AND_ASSIGN(MinidumpContextWriter);
};
//! \brief The writer for a MinidumpContextX86 structure in a minidump file.
class MinidumpContextX86Writer final : public MinidumpContextWriter {
public:
MinidumpContextX86Writer();
virtual ~MinidumpContextX86Writer();
//! \brief Returns a pointer to the context structure that this object will
//! write.
//!
//! \attention This returns a non-`const` pointer to this objects private
//! data so that a caller can populate the context structure directly.
//! This is done because providing setter interfaces to each field in the
//! context structure would be unwieldy and cumbersome. Care must be taken
//! to populate the context structure correctly. The context structure
//! must only be modified while this object is in the #kStateMutable
//! state.
MinidumpContextX86* context() { return &context_; }
protected:
// MinidumpWritable:
virtual bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpContextWriter:
virtual size_t ContextSize() const override;
private:
MinidumpContextX86 context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpContextX86Writer);
};
//! \brief The writer for a MinidumpContextAMD64 structure in a minidump file.
class MinidumpContextAMD64Writer final : public MinidumpContextWriter {
public:
MinidumpContextAMD64Writer();
virtual ~MinidumpContextAMD64Writer();
//! \brief Returns a pointer to the context structure that this object will
//! write.
//!
//! \attention This returns a non-`const` pointer to this objects private
//! data so that a caller can populate the context structure directly.
//! This is done because providing setter interfaces to each field in the
//! context structure would be unwieldy and cumbersome. Care must be taken
//! to populate the context structure correctly. The context structure
//! must only be modified while this object is in the #kStateMutable
//! state.
MinidumpContextAMD64* context() { return &context_; }
protected:
// MinidumpWritable:
virtual size_t Alignment() override;
virtual bool WriteObject(FileWriterInterface* file_writer) override;
// MinidumpContextWriter:
virtual size_t ContextSize() const override;
private:
MinidumpContextAMD64 context_;
DISALLOW_COPY_AND_ASSIGN(MinidumpContextAMD64Writer);
};
} // namespace crashpad
#endif // CRASHPAD_MINIDUMP_MINIDUMP_CONTEXT_WRITER_H_