mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-09 14:06:33 +00:00
Thread snapshots on Windows can have varying size
In a future CL we will make use of InitializeContext2 which can produce contexts of varying sizes - this makes the existing use of a union for wow/x64 contexts no longer feasible. The context union in process_reader_win is replaced with a (moveable, copyable) helper struct which currently only knows how to allocate the replaced WOW or CONTEXT sized unions. As this field is no longer a member of the Thread struct it cannot be passed into other functions as a reference, so instead a pointer is used in these functions. Bug: 1250098 Change-Id: Ied3fe971c0073bbdafc071217e1bb0f72350bb4e Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3538668 Commit-Queue: Alex Gough <ajgo@chromium.org> Reviewed-by: Joshua Peraza <jperaza@chromium.org>
This commit is contained in:
parent
4581a355b1
commit
a5b7e504c6
@ -36,12 +36,12 @@ static_assert(sizeof(CPUContextX86::Fsave) ==
|
|||||||
#endif // ARCH_CPU_X86
|
#endif // ARCH_CPU_X86
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool HasContextPart(const T& context, uint32_t bits) {
|
bool HasContextPart(const T* context, uint32_t bits) {
|
||||||
return (context.ContextFlags & bits) == bits;
|
return (context->ContextFlags & bits) == bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void CommonInitializeX86Context(const T& context, CPUContextX86* out) {
|
void CommonInitializeX86Context(const T* context, CPUContextX86* out) {
|
||||||
// This function assumes that the WOW64_CONTEXT_* and x86 CONTEXT_* values
|
// This function assumes that the WOW64_CONTEXT_* and x86 CONTEXT_* values
|
||||||
// for ContextFlags are identical. This can be tested when targeting 32-bit
|
// for ContextFlags are identical. This can be tested when targeting 32-bit
|
||||||
// x86.
|
// x86.
|
||||||
@ -72,54 +72,54 @@ void CommonInitializeX86Context(const T& context, CPUContextX86* out) {
|
|||||||
<< "non-x86 context";
|
<< "non-x86 context";
|
||||||
|
|
||||||
if (HasContextPart(context, WOW64_CONTEXT_CONTROL)) {
|
if (HasContextPart(context, WOW64_CONTEXT_CONTROL)) {
|
||||||
out->ebp = context.Ebp;
|
out->ebp = context->Ebp;
|
||||||
out->eip = context.Eip;
|
out->eip = context->Eip;
|
||||||
out->cs = static_cast<uint16_t>(context.SegCs);
|
out->cs = static_cast<uint16_t>(context->SegCs);
|
||||||
out->eflags = context.EFlags;
|
out->eflags = context->EFlags;
|
||||||
out->esp = context.Esp;
|
out->esp = context->Esp;
|
||||||
out->ss = static_cast<uint16_t>(context.SegSs);
|
out->ss = static_cast<uint16_t>(context->SegSs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, WOW64_CONTEXT_INTEGER)) {
|
if (HasContextPart(context, WOW64_CONTEXT_INTEGER)) {
|
||||||
out->eax = context.Eax;
|
out->eax = context->Eax;
|
||||||
out->ebx = context.Ebx;
|
out->ebx = context->Ebx;
|
||||||
out->ecx = context.Ecx;
|
out->ecx = context->Ecx;
|
||||||
out->edx = context.Edx;
|
out->edx = context->Edx;
|
||||||
out->edi = context.Edi;
|
out->edi = context->Edi;
|
||||||
out->esi = context.Esi;
|
out->esi = context->Esi;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, WOW64_CONTEXT_SEGMENTS)) {
|
if (HasContextPart(context, WOW64_CONTEXT_SEGMENTS)) {
|
||||||
out->ds = static_cast<uint16_t>(context.SegDs);
|
out->ds = static_cast<uint16_t>(context->SegDs);
|
||||||
out->es = static_cast<uint16_t>(context.SegEs);
|
out->es = static_cast<uint16_t>(context->SegEs);
|
||||||
out->fs = static_cast<uint16_t>(context.SegFs);
|
out->fs = static_cast<uint16_t>(context->SegFs);
|
||||||
out->gs = static_cast<uint16_t>(context.SegGs);
|
out->gs = static_cast<uint16_t>(context->SegGs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, WOW64_CONTEXT_DEBUG_REGISTERS)) {
|
if (HasContextPart(context, WOW64_CONTEXT_DEBUG_REGISTERS)) {
|
||||||
out->dr0 = context.Dr0;
|
out->dr0 = context->Dr0;
|
||||||
out->dr1 = context.Dr1;
|
out->dr1 = context->Dr1;
|
||||||
out->dr2 = context.Dr2;
|
out->dr2 = context->Dr2;
|
||||||
out->dr3 = context.Dr3;
|
out->dr3 = context->Dr3;
|
||||||
|
|
||||||
// DR4 and DR5 are obsolete synonyms for DR6 and DR7, see
|
// DR4 and DR5 are obsolete synonyms for DR6 and DR7, see
|
||||||
// https://en.wikipedia.org/wiki/X86_debug_register.
|
// https://en.wikipedia.org/wiki/X86_debug_register.
|
||||||
out->dr4 = context.Dr6;
|
out->dr4 = context->Dr6;
|
||||||
out->dr5 = context.Dr7;
|
out->dr5 = context->Dr7;
|
||||||
|
|
||||||
out->dr6 = context.Dr6;
|
out->dr6 = context->Dr6;
|
||||||
out->dr7 = context.Dr7;
|
out->dr7 = context->Dr7;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, WOW64_CONTEXT_EXTENDED_REGISTERS)) {
|
if (HasContextPart(context, WOW64_CONTEXT_EXTENDED_REGISTERS)) {
|
||||||
static_assert(sizeof(out->fxsave) == sizeof(context.ExtendedRegisters),
|
static_assert(sizeof(out->fxsave) == sizeof(context->ExtendedRegisters),
|
||||||
"fxsave types must be equivalent");
|
"fxsave types must be equivalent");
|
||||||
memcpy(&out->fxsave, &context.ExtendedRegisters, sizeof(out->fxsave));
|
memcpy(&out->fxsave, &context->ExtendedRegisters, sizeof(out->fxsave));
|
||||||
} else if (HasContextPart(context, WOW64_CONTEXT_FLOATING_POINT)) {
|
} else if (HasContextPart(context, WOW64_CONTEXT_FLOATING_POINT)) {
|
||||||
// The static_assert that validates this cast can’t be here because it
|
// The static_assert that validates this cast can’t be here because it
|
||||||
// relies on field names that vary based on the template parameter.
|
// relies on field names that vary based on the template parameter.
|
||||||
CPUContextX86::FsaveToFxsave(
|
CPUContextX86::FsaveToFxsave(
|
||||||
*reinterpret_cast<const CPUContextX86::Fsave*>(&context.FloatSave),
|
*reinterpret_cast<const CPUContextX86::Fsave*>(&context->FloatSave),
|
||||||
&out->fxsave);
|
&out->fxsave);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,101 +128,101 @@ void CommonInitializeX86Context(const T& context, CPUContextX86* out) {
|
|||||||
|
|
||||||
#if defined(ARCH_CPU_X86)
|
#if defined(ARCH_CPU_X86)
|
||||||
|
|
||||||
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out) {
|
void InitializeX86Context(const CONTEXT* context, CPUContextX86* out) {
|
||||||
CommonInitializeX86Context(context, out);
|
CommonInitializeX86Context(context, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(ARCH_CPU_X86_64)
|
#elif defined(ARCH_CPU_X86_64)
|
||||||
|
|
||||||
void InitializeX86Context(const WOW64_CONTEXT& context, CPUContextX86* out) {
|
void InitializeX86Context(const WOW64_CONTEXT* context, CPUContextX86* out) {
|
||||||
CommonInitializeX86Context(context, out);
|
CommonInitializeX86Context(context, out);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeX64Context(const CONTEXT& context, CPUContextX86_64* out) {
|
void InitializeX64Context(const CONTEXT* context, CPUContextX86_64* out) {
|
||||||
memset(out, 0, sizeof(*out));
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
LOG_IF(ERROR, !HasContextPart(context, CONTEXT_AMD64)) << "non-x64 context";
|
LOG_IF(ERROR, !HasContextPart(context, CONTEXT_AMD64)) << "non-x64 context";
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_CONTROL)) {
|
if (HasContextPart(context, CONTEXT_CONTROL)) {
|
||||||
out->cs = context.SegCs;
|
out->cs = context->SegCs;
|
||||||
out->rflags = context.EFlags;
|
out->rflags = context->EFlags;
|
||||||
out->rip = context.Rip;
|
out->rip = context->Rip;
|
||||||
out->rsp = context.Rsp;
|
out->rsp = context->Rsp;
|
||||||
// SegSs ignored.
|
// SegSs ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_INTEGER)) {
|
if (HasContextPart(context, CONTEXT_INTEGER)) {
|
||||||
out->rax = context.Rax;
|
out->rax = context->Rax;
|
||||||
out->rbx = context.Rbx;
|
out->rbx = context->Rbx;
|
||||||
out->rcx = context.Rcx;
|
out->rcx = context->Rcx;
|
||||||
out->rdx = context.Rdx;
|
out->rdx = context->Rdx;
|
||||||
out->rdi = context.Rdi;
|
out->rdi = context->Rdi;
|
||||||
out->rsi = context.Rsi;
|
out->rsi = context->Rsi;
|
||||||
out->rbp = context.Rbp;
|
out->rbp = context->Rbp;
|
||||||
out->r8 = context.R8;
|
out->r8 = context->R8;
|
||||||
out->r9 = context.R9;
|
out->r9 = context->R9;
|
||||||
out->r10 = context.R10;
|
out->r10 = context->R10;
|
||||||
out->r11 = context.R11;
|
out->r11 = context->R11;
|
||||||
out->r12 = context.R12;
|
out->r12 = context->R12;
|
||||||
out->r13 = context.R13;
|
out->r13 = context->R13;
|
||||||
out->r14 = context.R14;
|
out->r14 = context->R14;
|
||||||
out->r15 = context.R15;
|
out->r15 = context->R15;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_SEGMENTS)) {
|
if (HasContextPart(context, CONTEXT_SEGMENTS)) {
|
||||||
out->fs = context.SegFs;
|
out->fs = context->SegFs;
|
||||||
out->gs = context.SegGs;
|
out->gs = context->SegGs;
|
||||||
// SegDs ignored.
|
// SegDs ignored.
|
||||||
// SegEs ignored.
|
// SegEs ignored.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_DEBUG_REGISTERS)) {
|
if (HasContextPart(context, CONTEXT_DEBUG_REGISTERS)) {
|
||||||
out->dr0 = context.Dr0;
|
out->dr0 = context->Dr0;
|
||||||
out->dr1 = context.Dr1;
|
out->dr1 = context->Dr1;
|
||||||
out->dr2 = context.Dr2;
|
out->dr2 = context->Dr2;
|
||||||
out->dr3 = context.Dr3;
|
out->dr3 = context->Dr3;
|
||||||
|
|
||||||
// DR4 and DR5 are obsolete synonyms for DR6 and DR7, see
|
// DR4 and DR5 are obsolete synonyms for DR6 and DR7, see
|
||||||
// https://en.wikipedia.org/wiki/X86_debug_register.
|
// https://en.wikipedia.org/wiki/X86_debug_register.
|
||||||
out->dr4 = context.Dr6;
|
out->dr4 = context->Dr6;
|
||||||
out->dr5 = context.Dr7;
|
out->dr5 = context->Dr7;
|
||||||
|
|
||||||
out->dr6 = context.Dr6;
|
out->dr6 = context->Dr6;
|
||||||
out->dr7 = context.Dr7;
|
out->dr7 = context->Dr7;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_FLOATING_POINT)) {
|
if (HasContextPart(context, CONTEXT_FLOATING_POINT)) {
|
||||||
static_assert(sizeof(out->fxsave) == sizeof(context.FltSave),
|
static_assert(sizeof(out->fxsave) == sizeof(context->FltSave),
|
||||||
"types must be equivalent");
|
"types must be equivalent");
|
||||||
memcpy(&out->fxsave, &context.FltSave, sizeof(out->fxsave));
|
memcpy(&out->fxsave, &context->FltSave, sizeof(out->fxsave));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(ARCH_CPU_ARM64)
|
#elif defined(ARCH_CPU_ARM64)
|
||||||
|
|
||||||
void InitializeARM64Context(const CONTEXT& context, CPUContextARM64* out) {
|
void InitializeARM64Context(const CONTEXT* context, CPUContextARM64* out) {
|
||||||
memset(out, 0, sizeof(*out));
|
memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
LOG_IF(ERROR, !HasContextPart(context, CONTEXT_ARM64)) << "non-arm64 context";
|
LOG_IF(ERROR, !HasContextPart(context, CONTEXT_ARM64)) << "non-arm64 context";
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_CONTROL)) {
|
if (HasContextPart(context, CONTEXT_CONTROL)) {
|
||||||
out->spsr = context.Cpsr;
|
out->spsr = context->Cpsr;
|
||||||
out->pc = context.Pc;
|
out->pc = context->Pc;
|
||||||
out->regs[30] = context.Lr;
|
out->regs[30] = context->Lr;
|
||||||
out->sp = context.Sp;
|
out->sp = context->Sp;
|
||||||
out->regs[29] = context.Fp;
|
out->regs[29] = context->Fp;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_INTEGER)) {
|
if (HasContextPart(context, CONTEXT_INTEGER)) {
|
||||||
memcpy(&out->regs[0], &context.X0, 18 * sizeof(context.X0));
|
memcpy(&out->regs[0], &context->X0, 18 * sizeof(context->X0));
|
||||||
// Don't copy x18 which is reserved as platform register.
|
// Don't copy x18 which is reserved as platform register.
|
||||||
memcpy(&out->regs[19], &context.X19, 10 * sizeof(context.X0));
|
memcpy(&out->regs[19], &context->X19, 10 * sizeof(context->X0));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HasContextPart(context, CONTEXT_FLOATING_POINT)) {
|
if (HasContextPart(context, CONTEXT_FLOATING_POINT)) {
|
||||||
static_assert(sizeof(out->fpsimd) == sizeof(context.V),
|
static_assert(sizeof(out->fpsimd) == sizeof(context->V),
|
||||||
"types must be equivalent");
|
"types must be equivalent");
|
||||||
memcpy(&out->fpsimd, &context.V, sizeof(out->fpsimd));
|
memcpy(&out->fpsimd, &context->V, sizeof(out->fpsimd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,7 +29,7 @@ struct CPUContextARM64;
|
|||||||
|
|
||||||
//! \brief Initializes a CPUContextX86 structure from a native context structure
|
//! \brief Initializes a CPUContextX86 structure from a native context structure
|
||||||
//! on Windows.
|
//! on Windows.
|
||||||
void InitializeX86Context(const CONTEXT& context, CPUContextX86* out);
|
void InitializeX86Context(const CONTEXT* context, CPUContextX86* out);
|
||||||
|
|
||||||
#endif // ARCH_CPU_X86
|
#endif // ARCH_CPU_X86
|
||||||
|
|
||||||
@ -37,11 +37,12 @@ void InitializeX86Context(const CONTEXT& context, CPUContextX86* out);
|
|||||||
|
|
||||||
//! \brief Initializes a CPUContextX86 structure from a native context structure
|
//! \brief Initializes a CPUContextX86 structure from a native context structure
|
||||||
//! on Windows.
|
//! on Windows.
|
||||||
void InitializeX86Context(const WOW64_CONTEXT& context, CPUContextX86* out);
|
void InitializeX86Context(const WOW64_CONTEXT* context, CPUContextX86* out);
|
||||||
|
|
||||||
//! \brief Initializes a CPUContextX86_64 structure from a native context
|
//! \brief Initializes a CPUContextX86_64 structure from a native context
|
||||||
//! structure on Windows.
|
//! structure on Windows.
|
||||||
void InitializeX64Context(const CONTEXT& context, CPUContextX86_64* out);
|
//! Only reads a max of sizeof(CONTEXT) so will not initialize extended values.
|
||||||
|
void InitializeX64Context(const CONTEXT* context, CPUContextX86_64* out);
|
||||||
|
|
||||||
#endif // ARCH_CPU_X86_64
|
#endif // ARCH_CPU_X86_64
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ void InitializeX64Context(const CONTEXT& context, CPUContextX86_64* out);
|
|||||||
|
|
||||||
//! \brief Initializes a CPUContextARM64 structure from a native context
|
//! \brief Initializes a CPUContextARM64 structure from a native context
|
||||||
//! structure on Windows.
|
//! structure on Windows.
|
||||||
void InitializeARM64Context(const CONTEXT& context, CPUContextARM64* out);
|
void InitializeARM64Context(const CONTEXT* context, CPUContextARM64* out);
|
||||||
|
|
||||||
#endif // ARCH_CPU_ARM64
|
#endif // ARCH_CPU_ARM64
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ void TestInitializeX86Context() {
|
|||||||
// directly from the supplied thread, float, and debug state parameters.
|
// directly from the supplied thread, float, and debug state parameters.
|
||||||
{
|
{
|
||||||
CPUContextX86 cpu_context_x86 = {};
|
CPUContextX86 cpu_context_x86 = {};
|
||||||
InitializeX86Context(context, &cpu_context_x86);
|
InitializeX86Context(&context, &cpu_context_x86);
|
||||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||||
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
EXPECT_EQ(cpu_context_x86.fxsave.ftw, 2u);
|
||||||
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
EXPECT_EQ(cpu_context_x86.dr0, 3u);
|
||||||
@ -73,7 +73,7 @@ void TestInitializeX86Context_FsaveWithoutFxsave() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
CPUContextX86 cpu_context_x86 = {};
|
CPUContextX86 cpu_context_x86 = {};
|
||||||
InitializeX86Context(context, &cpu_context_x86);
|
InitializeX86Context(&context, &cpu_context_x86);
|
||||||
|
|
||||||
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
EXPECT_EQ(cpu_context_x86.eax, 1u);
|
||||||
|
|
||||||
@ -117,7 +117,7 @@ TEST(CPUContextWin, InitializeX64Context) {
|
|||||||
// set directly from the supplied thread, float, and debug state parameters.
|
// set directly from the supplied thread, float, and debug state parameters.
|
||||||
{
|
{
|
||||||
CPUContextX86_64 cpu_context_x86_64 = {};
|
CPUContextX86_64 cpu_context_x86_64 = {};
|
||||||
InitializeX64Context(context, &cpu_context_x86_64);
|
InitializeX64Context(&context, &cpu_context_x86_64);
|
||||||
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
EXPECT_EQ(cpu_context_x86_64.rax, 10u);
|
||||||
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
EXPECT_EQ(cpu_context_x86_64.fxsave.ftw, 11u);
|
||||||
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
EXPECT_EQ(cpu_context_x86_64.dr0, 12u);
|
||||||
|
@ -36,7 +36,7 @@ using Context32 = CONTEXT;
|
|||||||
using Context32 = WOW64_CONTEXT;
|
using Context32 = WOW64_CONTEXT;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void NativeContextToCPUContext32(const Context32& context_record,
|
void NativeContextToCPUContext32(const Context32* context_record,
|
||||||
CPUContext* context,
|
CPUContext* context,
|
||||||
CPUContextUnion* context_union) {
|
CPUContextUnion* context_union) {
|
||||||
context->architecture = kCPUArchitectureX86;
|
context->architecture = kCPUArchitectureX86;
|
||||||
@ -46,7 +46,7 @@ void NativeContextToCPUContext32(const Context32& context_record,
|
|||||||
#endif // ARCH_CPU_X86_FAMILY
|
#endif // ARCH_CPU_X86_FAMILY
|
||||||
|
|
||||||
#if defined(ARCH_CPU_64_BITS)
|
#if defined(ARCH_CPU_64_BITS)
|
||||||
void NativeContextToCPUContext64(const CONTEXT& context_record,
|
void NativeContextToCPUContext64(const CONTEXT* context_record,
|
||||||
CPUContext* context,
|
CPUContext* context,
|
||||||
CPUContextUnion* context_union) {
|
CPUContextUnion* context_union) {
|
||||||
#if defined(ARCH_CPU_X86_64)
|
#if defined(ARCH_CPU_X86_64)
|
||||||
@ -190,7 +190,7 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers(
|
|||||||
ProcessReaderWin* process_reader,
|
ProcessReaderWin* process_reader,
|
||||||
WinVMAddress exception_pointers_address,
|
WinVMAddress exception_pointers_address,
|
||||||
DWORD exception_thread_id,
|
DWORD exception_thread_id,
|
||||||
void (*native_to_cpu_context)(const ContextType& context_record,
|
void (*native_to_cpu_context)(const ContextType* context_record,
|
||||||
CPUContext* context,
|
CPUContext* context,
|
||||||
CPUContextUnion* context_union)) {
|
CPUContextUnion* context_union)) {
|
||||||
ExceptionPointersType exception_pointers;
|
ExceptionPointersType exception_pointers;
|
||||||
@ -232,10 +232,9 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers(
|
|||||||
for (const auto& thread : process_reader->Threads()) {
|
for (const auto& thread : process_reader->Threads()) {
|
||||||
if (thread.id == blame_thread_id) {
|
if (thread.id == blame_thread_id) {
|
||||||
thread_id_ = blame_thread_id;
|
thread_id_ = blame_thread_id;
|
||||||
native_to_cpu_context(
|
native_to_cpu_context(thread.context.context<const ContextType>(),
|
||||||
*reinterpret_cast<const ContextType*>(&thread.context),
|
&context_,
|
||||||
&context_,
|
&context_union_);
|
||||||
&context_union_);
|
|
||||||
exception_address_ = context_.InstructionPointer();
|
exception_address_ = context_.InstructionPointer();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -266,7 +265,7 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
native_to_cpu_context(context_record, &context_, &context_union_);
|
native_to_cpu_context(&context_record, &context_, &context_union_);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -93,7 +93,7 @@ class ExceptionSnapshotWin final : public ExceptionSnapshot {
|
|||||||
ProcessReaderWin* process_reader,
|
ProcessReaderWin* process_reader,
|
||||||
WinVMAddress exception_pointers_address,
|
WinVMAddress exception_pointers_address,
|
||||||
DWORD exception_thread_id,
|
DWORD exception_thread_id,
|
||||||
void (*native_to_cpu_context)(const ContextType& context_record,
|
void (*native_to_cpu_context)(const ContextType* context_record,
|
||||||
CPUContext* context,
|
CPUContext* context,
|
||||||
CPUContextUnion* context_union));
|
CPUContextUnion* context_union));
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ bool FillThreadContextAndSuspendCount(HANDLE thread_handle,
|
|||||||
DCHECK(suspension_state == ProcessSuspensionState::kRunning);
|
DCHECK(suspension_state == ProcessSuspensionState::kRunning);
|
||||||
thread->suspend_count = 0;
|
thread->suspend_count = 0;
|
||||||
DCHECK(!is_64_reading_32);
|
DCHECK(!is_64_reading_32);
|
||||||
CaptureContext(&thread->context.native);
|
thread->context.InitializeFromCurrentThread();
|
||||||
} else {
|
} else {
|
||||||
DWORD previous_suspend_count = SuspendThread(thread_handle);
|
DWORD previous_suspend_count = SuspendThread(thread_handle);
|
||||||
if (previous_suspend_count == static_cast<DWORD>(-1)) {
|
if (previous_suspend_count == static_cast<DWORD>(-1)) {
|
||||||
@ -162,25 +162,18 @@ bool FillThreadContextAndSuspendCount(HANDLE thread_handle,
|
|||||||
(suspension_state == ProcessSuspensionState::kSuspended ? 1 : 0);
|
(suspension_state == ProcessSuspensionState::kSuspended ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&thread->context, 0, sizeof(thread->context));
|
|
||||||
#if defined(ARCH_CPU_32_BITS)
|
#if defined(ARCH_CPU_32_BITS)
|
||||||
const bool is_native = true;
|
const bool is_native = true;
|
||||||
#elif defined(ARCH_CPU_64_BITS)
|
#elif defined(ARCH_CPU_64_BITS)
|
||||||
const bool is_native = !is_64_reading_32;
|
const bool is_native = !is_64_reading_32;
|
||||||
if (is_64_reading_32) {
|
if (is_64_reading_32) {
|
||||||
thread->context.wow64.ContextFlags = CONTEXT_ALL;
|
if (!thread->context.InitializeWow64(thread_handle))
|
||||||
if (!Wow64GetThreadContext(thread_handle, &thread->context.wow64)) {
|
|
||||||
PLOG(ERROR) << "Wow64GetThreadContext";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (is_native) {
|
if (is_native) {
|
||||||
thread->context.native.ContextFlags = CONTEXT_ALL;
|
if (!thread->context.InitializeNative(thread_handle))
|
||||||
if (!GetThreadContext(thread_handle, &thread->context.native)) {
|
|
||||||
PLOG(ERROR) << "GetThreadContext";
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ResumeThread(thread_handle)) {
|
if (!ResumeThread(thread_handle)) {
|
||||||
@ -194,6 +187,39 @@ bool FillThreadContextAndSuspendCount(HANDLE thread_handle,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
ProcessReaderWin::ThreadContext::ThreadContext()
|
||||||
|
: offset_(0), initialized_(false), data_() {}
|
||||||
|
|
||||||
|
void ProcessReaderWin::ThreadContext::InitializeFromCurrentThread() {
|
||||||
|
data_.resize(sizeof(CONTEXT));
|
||||||
|
initialized_ = true;
|
||||||
|
CaptureContext(context<CONTEXT>());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessReaderWin::ThreadContext::InitializeNative(HANDLE thread_handle) {
|
||||||
|
data_.resize(sizeof(CONTEXT));
|
||||||
|
initialized_ = true;
|
||||||
|
context<CONTEXT>()->ContextFlags = CONTEXT_ALL;
|
||||||
|
if (!GetThreadContext(thread_handle, context<CONTEXT>())) {
|
||||||
|
PLOG(ERROR) << "GetThreadContext";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(ARCH_CPU_64_BITS)
|
||||||
|
bool ProcessReaderWin::ThreadContext::InitializeWow64(HANDLE thread_handle) {
|
||||||
|
data_.resize(sizeof(WOW64_CONTEXT));
|
||||||
|
initialized_ = true;
|
||||||
|
context<WOW64_CONTEXT>()->ContextFlags = CONTEXT_ALL;
|
||||||
|
if (!Wow64GetThreadContext(thread_handle, context<WOW64_CONTEXT>())) {
|
||||||
|
PLOG(ERROR) << "Wow64GetThreadContext";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
ProcessReaderWin::Thread::Thread()
|
ProcessReaderWin::Thread::Thread()
|
||||||
: context(),
|
: context(),
|
||||||
id(0),
|
id(0),
|
||||||
@ -203,8 +229,7 @@ ProcessReaderWin::Thread::Thread()
|
|||||||
stack_region_size(0),
|
stack_region_size(0),
|
||||||
suspend_count(0),
|
suspend_count(0),
|
||||||
priority_class(0),
|
priority_class(0),
|
||||||
priority(0) {
|
priority(0) {}
|
||||||
}
|
|
||||||
|
|
||||||
ProcessReaderWin::ProcessReaderWin()
|
ProcessReaderWin::ProcessReaderWin()
|
||||||
: process_(INVALID_HANDLE_VALUE),
|
: process_(INVALID_HANDLE_VALUE),
|
||||||
|
@ -40,17 +40,39 @@ enum class ProcessSuspensionState : bool {
|
|||||||
//! \brief Accesses information about another process, identified by a `HANDLE`.
|
//! \brief Accesses information about another process, identified by a `HANDLE`.
|
||||||
class ProcessReaderWin {
|
class ProcessReaderWin {
|
||||||
public:
|
public:
|
||||||
|
//! \brief Helper to make the context copyable and resizable.
|
||||||
|
class ThreadContext {
|
||||||
|
public:
|
||||||
|
ThreadContext();
|
||||||
|
~ThreadContext() {}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
T* context() const {
|
||||||
|
DCHECK(initialized_);
|
||||||
|
return reinterpret_cast<T*>(
|
||||||
|
const_cast<unsigned char*>(data_.data() + offset_));
|
||||||
|
}
|
||||||
|
#if defined(ARCH_CPU_64_BITS)
|
||||||
|
bool InitializeWow64(HANDLE thread_handle);
|
||||||
|
#endif
|
||||||
|
void InitializeFromCurrentThread();
|
||||||
|
bool InitializeNative(HANDLE thread_handle);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is usually 0 but Windows might cause it to be positive when
|
||||||
|
// fetching the extended context. This needs to be adjusted after
|
||||||
|
// calls to InitializeContext2().
|
||||||
|
size_t offset_;
|
||||||
|
bool initialized_;
|
||||||
|
std::vector<unsigned char> data_;
|
||||||
|
};
|
||||||
|
|
||||||
//! \brief Contains information about a thread that belongs to a process.
|
//! \brief Contains information about a thread that belongs to a process.
|
||||||
struct Thread {
|
struct Thread {
|
||||||
Thread();
|
Thread();
|
||||||
~Thread() {}
|
~Thread() {}
|
||||||
|
|
||||||
union {
|
ThreadContext context;
|
||||||
CONTEXT native;
|
|
||||||
#if defined(ARCH_CPU_64_BITS)
|
|
||||||
WOW64_CONTEXT wow64;
|
|
||||||
#endif
|
|
||||||
} context;
|
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
WinVMAddress teb_address;
|
WinVMAddress teb_address;
|
||||||
WinVMSize teb_size;
|
WinVMSize teb_size;
|
||||||
|
@ -111,7 +111,8 @@ TEST(ProcessReaderWin, SelfOneThread) {
|
|||||||
ASSERT_GE(threads.size(), 1u);
|
ASSERT_GE(threads.size(), 1u);
|
||||||
|
|
||||||
EXPECT_EQ(threads[0].id, GetCurrentThreadId());
|
EXPECT_EQ(threads[0].id, GetCurrentThreadId());
|
||||||
EXPECT_NE(ProgramCounterFromCONTEXT(&threads[0].context.native), nullptr);
|
EXPECT_NE(ProgramCounterFromCONTEXT(threads[0].context.context<CONTEXT>()),
|
||||||
|
nullptr);
|
||||||
EXPECT_EQ(threads[0].suspend_count, 0u);
|
EXPECT_EQ(threads[0].suspend_count, 0u);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,21 +67,25 @@ bool ThreadSnapshotWin::Initialize(
|
|||||||
#if defined(ARCH_CPU_X86)
|
#if defined(ARCH_CPU_X86)
|
||||||
context_.architecture = kCPUArchitectureX86;
|
context_.architecture = kCPUArchitectureX86;
|
||||||
context_.x86 = &context_union_.x86;
|
context_.x86 = &context_union_.x86;
|
||||||
InitializeX86Context(process_reader_thread.context.native, context_.x86);
|
InitializeX86Context(process_reader_thread.context.context<CONTEXT>(),
|
||||||
|
context_.x86);
|
||||||
#elif defined(ARCH_CPU_X86_64)
|
#elif defined(ARCH_CPU_X86_64)
|
||||||
if (process_reader->Is64Bit()) {
|
if (process_reader->Is64Bit()) {
|
||||||
context_.architecture = kCPUArchitectureX86_64;
|
context_.architecture = kCPUArchitectureX86_64;
|
||||||
context_.x86_64 = &context_union_.x86_64;
|
context_.x86_64 = &context_union_.x86_64;
|
||||||
InitializeX64Context(process_reader_thread.context.native, context_.x86_64);
|
InitializeX64Context(process_reader_thread.context.context<CONTEXT>(),
|
||||||
|
context_.x86_64);
|
||||||
} else {
|
} else {
|
||||||
context_.architecture = kCPUArchitectureX86;
|
context_.architecture = kCPUArchitectureX86;
|
||||||
context_.x86 = &context_union_.x86;
|
context_.x86 = &context_union_.x86;
|
||||||
InitializeX86Context(process_reader_thread.context.wow64, context_.x86);
|
InitializeX86Context(process_reader_thread.context.context<WOW64_CONTEXT>(),
|
||||||
|
context_.x86);
|
||||||
}
|
}
|
||||||
#elif defined(ARCH_CPU_ARM64)
|
#elif defined(ARCH_CPU_ARM64)
|
||||||
context_.architecture = kCPUArchitectureARM64;
|
context_.architecture = kCPUArchitectureARM64;
|
||||||
context_.arm64 = &context_union_.arm64;
|
context_.arm64 = &context_union_.arm64;
|
||||||
InitializeARM64Context(process_reader_thread.context.native, context_.arm64);
|
InitializeARM64Context(process_reader_thread.context.context<CONTEXT>(),
|
||||||
|
context_.arm64);
|
||||||
#else
|
#else
|
||||||
#error Unsupported Windows Arch
|
#error Unsupported Windows Arch
|
||||||
#endif // ARCH_CPU_X86
|
#endif // ARCH_CPU_X86
|
||||||
|
Loading…
x
Reference in New Issue
Block a user