mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-28 15:50:26 +08:00
52c2f6edfc
and its test. Minidump context structures now interoperate more easily with snapshot CPUContext structures, while maintaining identical layout to before. This is facilitated by reusing the Fxsave types for the substructures which were completely identical, and by using compatible logic to initialize the minidump and snapshot structures for testing. TEST=minidump_test, snapshot_test R=rsesek@chromium.org Review URL: https://codereview.chromium.org/686353004
212 lines
6.9 KiB
C++
212 lines
6.9 KiB
C++
// 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 <string.h>
|
||
|
||
#include "base/logging.h"
|
||
#include "snapshot/cpu_context.h"
|
||
#include "util/file/file_writer.h"
|
||
|
||
namespace crashpad {
|
||
|
||
MinidumpContextWriter::~MinidumpContextWriter() {
|
||
}
|
||
|
||
// static
|
||
scoped_ptr<MinidumpContextWriter> MinidumpContextWriter::CreateFromSnapshot(
|
||
const CPUContext* context_snapshot) {
|
||
scoped_ptr<MinidumpContextWriter> context;
|
||
|
||
switch (context_snapshot->architecture) {
|
||
case kCPUArchitectureX86: {
|
||
MinidumpContextX86Writer* context_x86 = new MinidumpContextX86Writer();
|
||
context.reset(context_x86);
|
||
context_x86->InitializeFromSnapshot(context_snapshot->x86);
|
||
break;
|
||
}
|
||
|
||
case kCPUArchitectureX86_64: {
|
||
MinidumpContextAMD64Writer* context_amd64 =
|
||
new MinidumpContextAMD64Writer();
|
||
context.reset(context_amd64);
|
||
context_amd64->InitializeFromSnapshot(context_snapshot->x86_64);
|
||
break;
|
||
}
|
||
|
||
default: {
|
||
LOG(ERROR) << "unknown context architecture "
|
||
<< context_snapshot->architecture;
|
||
break;
|
||
}
|
||
}
|
||
|
||
return context;
|
||
}
|
||
|
||
size_t MinidumpContextWriter::SizeOfObject() {
|
||
DCHECK_GE(state(), kStateFrozen);
|
||
|
||
return ContextSize();
|
||
}
|
||
|
||
MinidumpContextX86Writer::MinidumpContextX86Writer()
|
||
: MinidumpContextWriter(), context_() {
|
||
context_.context_flags = kMinidumpContextX86;
|
||
}
|
||
|
||
MinidumpContextX86Writer::~MinidumpContextX86Writer() {
|
||
}
|
||
|
||
|
||
void MinidumpContextX86Writer::InitializeFromSnapshot(
|
||
const CPUContextX86* context_snapshot) {
|
||
DCHECK_EQ(state(), kStateMutable);
|
||
DCHECK_EQ(context_.context_flags, kMinidumpContextX86);
|
||
|
||
context_.context_flags = kMinidumpContextX86All;
|
||
|
||
context_.dr0 = context_snapshot->dr0;
|
||
context_.dr1 = context_snapshot->dr1;
|
||
context_.dr2 = context_snapshot->dr2;
|
||
context_.dr3 = context_snapshot->dr3;
|
||
context_.dr6 = context_snapshot->dr6;
|
||
context_.dr7 = context_snapshot->dr7;
|
||
|
||
// The contents of context_.float_save effectively alias everything in
|
||
// context_.fxsave that’s related to x87 FPU state. context_.float_save
|
||
// doesn’t carry state specific to SSE (or later), such as mxcsr and the xmm
|
||
// registers.
|
||
context_.float_save.control_word = context_snapshot->fxsave.fcw;
|
||
context_.float_save.status_word = context_snapshot->fxsave.fsw;
|
||
context_.float_save.tag_word =
|
||
CPUContextX86::FxsaveToFsaveTagWord(context_snapshot->fxsave.fsw,
|
||
context_snapshot->fxsave.ftw,
|
||
context_snapshot->fxsave.st_mm);
|
||
context_.float_save.error_offset = context_snapshot->fxsave.fpu_ip;
|
||
context_.float_save.error_selector = context_snapshot->fxsave.fpu_cs;
|
||
context_.float_save.data_offset = context_snapshot->fxsave.fpu_dp;
|
||
context_.float_save.data_selector = context_snapshot->fxsave.fpu_ds;
|
||
|
||
for (size_t index = 0, offset = 0;
|
||
index < arraysize(context_snapshot->fxsave.st_mm);
|
||
offset += sizeof(context_snapshot->fxsave.st_mm[index].st), ++index) {
|
||
memcpy(&context_.float_save.register_area[offset],
|
||
&context_snapshot->fxsave.st_mm[index].st,
|
||
sizeof(context_snapshot->fxsave.st_mm[index].st));
|
||
}
|
||
|
||
context_.gs = context_snapshot->gs;
|
||
context_.fs = context_snapshot->fs;
|
||
context_.es = context_snapshot->es;
|
||
context_.ds = context_snapshot->ds;
|
||
context_.edi = context_snapshot->edi;
|
||
context_.esi = context_snapshot->esi;
|
||
context_.ebx = context_snapshot->ebx;
|
||
context_.edx = context_snapshot->edx;
|
||
context_.ecx = context_snapshot->ecx;
|
||
context_.eax = context_snapshot->eax;
|
||
context_.ebp = context_snapshot->ebp;
|
||
context_.eip = context_snapshot->eip;
|
||
context_.cs = context_snapshot->cs;
|
||
context_.eflags = context_snapshot->eflags;
|
||
context_.esp = context_snapshot->esp;
|
||
context_.ss = context_snapshot->ss;
|
||
|
||
// This is effectively a memcpy() of a big structure.
|
||
context_.fxsave = context_snapshot->fxsave;
|
||
}
|
||
|
||
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() {
|
||
}
|
||
|
||
void MinidumpContextAMD64Writer::InitializeFromSnapshot(
|
||
const CPUContextX86_64* context_snapshot) {
|
||
DCHECK_EQ(state(), kStateMutable);
|
||
DCHECK_EQ(context_.context_flags, kMinidumpContextAMD64);
|
||
|
||
context_.context_flags = kMinidumpContextAMD64All;
|
||
|
||
context_.mx_csr = context_snapshot->fxsave.mxcsr;
|
||
context_.cs = context_snapshot->cs;
|
||
context_.fs = context_snapshot->fs;
|
||
context_.gs = context_snapshot->gs;
|
||
context_.eflags = context_snapshot->rflags;
|
||
context_.dr0 = context_snapshot->dr0;
|
||
context_.dr1 = context_snapshot->dr1;
|
||
context_.dr2 = context_snapshot->dr2;
|
||
context_.dr3 = context_snapshot->dr3;
|
||
context_.dr6 = context_snapshot->dr6;
|
||
context_.dr7 = context_snapshot->dr7;
|
||
context_.rax = context_snapshot->rax;
|
||
context_.rcx = context_snapshot->rcx;
|
||
context_.rdx = context_snapshot->rdx;
|
||
context_.rbx = context_snapshot->rbx;
|
||
context_.rsp = context_snapshot->rsp;
|
||
context_.rbp = context_snapshot->rbp;
|
||
context_.rsi = context_snapshot->rsi;
|
||
context_.rdi = context_snapshot->rdi;
|
||
context_.r8 = context_snapshot->r8;
|
||
context_.r9 = context_snapshot->r9;
|
||
context_.r10 = context_snapshot->r10;
|
||
context_.r11 = context_snapshot->r11;
|
||
context_.r12 = context_snapshot->r12;
|
||
context_.r13 = context_snapshot->r13;
|
||
context_.r14 = context_snapshot->r14;
|
||
context_.r15 = context_snapshot->r15;
|
||
context_.rip = context_snapshot->rip;
|
||
|
||
// This is effectively a memcpy() of a big structure.
|
||
context_.fxsave = context_snapshot->fxsave;
|
||
}
|
||
|
||
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
|