in src/processor/minidump.cc [463:1189]
bool MinidumpContext::Read(uint32_t expected_size) {
valid_ = false;
// Certain raw context types are currently assumed to have unique sizes.
if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) {
BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any "
<< "other raw context";
return false;
}
if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) {
BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any "
<< "other raw context";
return false;
}
if (!IsContextSizeUnique(sizeof(MDRawContextARM64_Old))) {
BPLOG(ERROR) << "sizeof(MDRawContextARM64_Old) cannot match the size of any "
<< "other raw context";
return false;
}
FreeContext();
// First, figure out what type of CPU this context structure is for.
// For some reason, the AMD64 Context doesn't have context_flags
// at the beginning of the structure, so special case it here.
if (expected_size == sizeof(MDRawContextAMD64)) {
BPLOG(INFO) << "MinidumpContext: looks like AMD64 context";
scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64());
if (!minidump_->ReadBytes(context_amd64.get(),
sizeof(MDRawContextAMD64))) {
BPLOG(ERROR) << "MinidumpContext could not read amd64 context";
return false;
}
if (minidump_->swap())
Swap(&context_amd64->context_flags);
uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK;
if (cpu_type == 0) {
if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
context_amd64->context_flags |= cpu_type;
} else {
BPLOG(ERROR) << "Failed to preserve the current stream position";
return false;
}
}
if (cpu_type != MD_CONTEXT_AMD64) {
// TODO: Fall through to switch below.
// https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
BPLOG(ERROR) << "MinidumpContext not actually amd64 context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext amd64 does not match system info";
return false;
}
// Normalize the 128-bit types in the dump.
// Since this is AMD64, by definition, the values are little-endian.
for (unsigned int vr_index = 0;
vr_index < MD_CONTEXT_AMD64_VR_COUNT;
++vr_index)
Normalize128(&context_amd64->vector_register[vr_index], false);
if (minidump_->swap()) {
Swap(&context_amd64->p1_home);
Swap(&context_amd64->p2_home);
Swap(&context_amd64->p3_home);
Swap(&context_amd64->p4_home);
Swap(&context_amd64->p5_home);
Swap(&context_amd64->p6_home);
// context_flags is already swapped
Swap(&context_amd64->mx_csr);
Swap(&context_amd64->cs);
Swap(&context_amd64->ds);
Swap(&context_amd64->es);
Swap(&context_amd64->fs);
Swap(&context_amd64->ss);
Swap(&context_amd64->eflags);
Swap(&context_amd64->dr0);
Swap(&context_amd64->dr1);
Swap(&context_amd64->dr2);
Swap(&context_amd64->dr3);
Swap(&context_amd64->dr6);
Swap(&context_amd64->dr7);
Swap(&context_amd64->rax);
Swap(&context_amd64->rcx);
Swap(&context_amd64->rdx);
Swap(&context_amd64->rbx);
Swap(&context_amd64->rsp);
Swap(&context_amd64->rbp);
Swap(&context_amd64->rsi);
Swap(&context_amd64->rdi);
Swap(&context_amd64->r8);
Swap(&context_amd64->r9);
Swap(&context_amd64->r10);
Swap(&context_amd64->r11);
Swap(&context_amd64->r12);
Swap(&context_amd64->r13);
Swap(&context_amd64->r14);
Swap(&context_amd64->r15);
Swap(&context_amd64->rip);
// FIXME: I'm not sure what actually determines
// which member of the union {flt_save, sse_registers}
// is valid. We're not currently using either,
// but it would be good to have them swapped properly.
for (unsigned int vr_index = 0;
vr_index < MD_CONTEXT_AMD64_VR_COUNT;
++vr_index)
Swap(&context_amd64->vector_register[vr_index]);
Swap(&context_amd64->vector_control);
Swap(&context_amd64->debug_control);
Swap(&context_amd64->last_branch_to_rip);
Swap(&context_amd64->last_branch_from_rip);
Swap(&context_amd64->last_exception_to_rip);
Swap(&context_amd64->last_exception_from_rip);
}
SetContextFlags(context_amd64->context_flags);
SetContextAMD64(context_amd64.release());
} else if (expected_size == sizeof(MDRawContextPPC64)) {
// |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext
// in the else case have 32 bits |context_flags|, so special case it here.
uint64_t context_flags;
if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
BPLOG(ERROR) << "MinidumpContext could not read context flags";
return false;
}
if (minidump_->swap())
Swap(&context_flags);
uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64());
if (cpu_type == 0) {
if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
context_ppc64->context_flags |= cpu_type;
} else {
BPLOG(ERROR) << "Failed to preserve the current stream position";
return false;
}
}
if (cpu_type != MD_CONTEXT_PPC64) {
// TODO: Fall through to switch below.
// https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
BPLOG(ERROR) << "MinidumpContext not actually ppc64 context";
return false;
}
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_ppc64->context_flags = context_flags;
size_t flags_size = sizeof(context_ppc64->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextPPC64) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read ppc64 context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info";
return false;
}
if (minidump_->swap()) {
// context_ppc64->context_flags was already swapped.
Swap(&context_ppc64->srr0);
Swap(&context_ppc64->srr1);
for (unsigned int gpr_index = 0;
gpr_index < MD_CONTEXT_PPC64_GPR_COUNT;
++gpr_index) {
Swap(&context_ppc64->gpr[gpr_index]);
}
Swap(&context_ppc64->cr);
Swap(&context_ppc64->xer);
Swap(&context_ppc64->lr);
Swap(&context_ppc64->ctr);
Swap(&context_ppc64->vrsave);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
++fpr_index) {
Swap(&context_ppc64->float_save.fpregs[fpr_index]);
}
// Don't swap context_ppc64->float_save.fpscr_pad because it is only
// used for padding.
Swap(&context_ppc64->float_save.fpscr);
for (unsigned int vr_index = 0;
vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
++vr_index) {
Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true);
Swap(&context_ppc64->vector_save.save_vr[vr_index]);
}
Swap(&context_ppc64->vector_save.save_vscr);
// Don't swap the padding fields in vector_save.
Swap(&context_ppc64->vector_save.save_vrvalid);
}
SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags));
// Check for data loss when converting context flags from uint64_t into
// uint32_t
if (static_cast<uint64_t>(GetContextFlags()) !=
context_ppc64->context_flags) {
BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags";
return false;
}
SetContextPPC64(context_ppc64.release());
} else if (expected_size == sizeof(MDRawContextARM64_Old)) {
// |context_flags| of MDRawContextARM64_Old is 64 bits, but other MDRawContext
// in the else case have 32 bits |context_flags|, so special case it here.
uint64_t context_flags;
BPLOG(INFO) << "MinidumpContext: looks like ARM64 context";
if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
BPLOG(ERROR) << "MinidumpContext could not read context flags";
return false;
}
if (minidump_->swap())
Swap(&context_flags);
scoped_ptr<MDRawContextARM64_Old> context_arm64(new MDRawContextARM64_Old());
uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
if (cpu_type == 0) {
if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
context_arm64->context_flags |= cpu_type;
} else {
BPLOG(ERROR) << "Failed to preserve the current stream position";
return false;
}
}
if (cpu_type != MD_CONTEXT_ARM64_OLD) {
// TODO: Fall through to switch below.
// https://bugs.chromium.org/p/google-breakpad/issues/detail?id=550
BPLOG(ERROR) << "MinidumpContext not actually arm64 context";
return false;
}
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_arm64->context_flags = context_flags;
size_t flags_size = sizeof(context_arm64->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextARM64_Old) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext arm64 does not match system info";
return false;
}
if (minidump_->swap()) {
// context_arm64->context_flags was already swapped.
for (unsigned int ireg_index = 0;
ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
++ireg_index) {
Swap(&context_arm64->iregs[ireg_index]);
}
Swap(&context_arm64->cpsr);
Swap(&context_arm64->float_save.fpsr);
Swap(&context_arm64->float_save.fpcr);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
++fpr_index) {
Normalize128(&context_arm64->float_save.regs[fpr_index],
minidump_->is_big_endian());
Swap(&context_arm64->float_save.regs[fpr_index]);
}
}
scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64());
ConvertOldARM64Context(*context_arm64.get(), new_context.get());
SetContextFlags(new_context->context_flags);
SetContextARM64(new_context.release());
} else {
uint32_t context_flags;
if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) {
BPLOG(ERROR) << "MinidumpContext could not read context flags";
return false;
}
if (minidump_->swap())
Swap(&context_flags);
uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK;
if (cpu_type == 0) {
// Unfortunately the flag for MD_CONTEXT_ARM that was taken
// from a Windows CE SDK header conflicts in practice with
// the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered,
// but handle dumps with the legacy value gracefully here.
if (context_flags & MD_CONTEXT_ARM_OLD) {
context_flags |= MD_CONTEXT_ARM;
context_flags &= ~MD_CONTEXT_ARM_OLD;
cpu_type = MD_CONTEXT_ARM;
}
}
if (cpu_type == 0) {
if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) {
context_flags |= cpu_type;
} else {
BPLOG(ERROR) << "Failed to preserve the current stream position";
return false;
}
}
// Allocate the context structure for the correct CPU and fill it. The
// casts are slightly unorthodox, but it seems better to do that than to
// maintain a separate pointer for each type of CPU context structure
// when only one of them will be used.
switch (cpu_type) {
case MD_CONTEXT_X86: {
if (expected_size != sizeof(MDRawContextX86)) {
BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " <<
expected_size << " != " << sizeof(MDRawContextX86);
return false;
}
scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_x86->context_flags = context_flags;
size_t flags_size = sizeof(context_x86->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextX86) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read x86 context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext x86 does not match system info";
return false;
}
if (minidump_->swap()) {
// context_x86->context_flags was already swapped.
Swap(&context_x86->dr0);
Swap(&context_x86->dr1);
Swap(&context_x86->dr2);
Swap(&context_x86->dr3);
Swap(&context_x86->dr6);
Swap(&context_x86->dr7);
Swap(&context_x86->float_save.control_word);
Swap(&context_x86->float_save.status_word);
Swap(&context_x86->float_save.tag_word);
Swap(&context_x86->float_save.error_offset);
Swap(&context_x86->float_save.error_selector);
Swap(&context_x86->float_save.data_offset);
Swap(&context_x86->float_save.data_selector);
// context_x86->float_save.register_area[] contains 8-bit quantities
// and does not need to be swapped.
Swap(&context_x86->float_save.cr0_npx_state);
Swap(&context_x86->gs);
Swap(&context_x86->fs);
Swap(&context_x86->es);
Swap(&context_x86->ds);
Swap(&context_x86->edi);
Swap(&context_x86->esi);
Swap(&context_x86->ebx);
Swap(&context_x86->edx);
Swap(&context_x86->ecx);
Swap(&context_x86->eax);
Swap(&context_x86->ebp);
Swap(&context_x86->eip);
Swap(&context_x86->cs);
Swap(&context_x86->eflags);
Swap(&context_x86->esp);
Swap(&context_x86->ss);
// context_x86->extended_registers[] contains 8-bit quantities and
// does not need to be swapped.
}
SetContextX86(context_x86.release());
break;
}
case MD_CONTEXT_PPC: {
if (expected_size != sizeof(MDRawContextPPC)) {
BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " <<
expected_size << " != " << sizeof(MDRawContextPPC);
return false;
}
scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_ppc->context_flags = context_flags;
size_t flags_size = sizeof(context_ppc->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextPPC) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read ppc context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext ppc does not match system info";
return false;
}
// Normalize the 128-bit types in the dump.
// Since this is PowerPC, by definition, the values are big-endian.
for (unsigned int vr_index = 0;
vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
++vr_index) {
Normalize128(&context_ppc->vector_save.save_vr[vr_index], true);
}
if (minidump_->swap()) {
// context_ppc->context_flags was already swapped.
Swap(&context_ppc->srr0);
Swap(&context_ppc->srr1);
for (unsigned int gpr_index = 0;
gpr_index < MD_CONTEXT_PPC_GPR_COUNT;
++gpr_index) {
Swap(&context_ppc->gpr[gpr_index]);
}
Swap(&context_ppc->cr);
Swap(&context_ppc->xer);
Swap(&context_ppc->lr);
Swap(&context_ppc->ctr);
Swap(&context_ppc->mq);
Swap(&context_ppc->vrsave);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT;
++fpr_index) {
Swap(&context_ppc->float_save.fpregs[fpr_index]);
}
// Don't swap context_ppc->float_save.fpscr_pad because it is only
// used for padding.
Swap(&context_ppc->float_save.fpscr);
for (unsigned int vr_index = 0;
vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT;
++vr_index) {
Swap(&context_ppc->vector_save.save_vr[vr_index]);
}
Swap(&context_ppc->vector_save.save_vscr);
// Don't swap the padding fields in vector_save.
Swap(&context_ppc->vector_save.save_vrvalid);
}
SetContextPPC(context_ppc.release());
break;
}
case MD_CONTEXT_SPARC: {
if (expected_size != sizeof(MDRawContextSPARC)) {
BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " <<
expected_size << " != " << sizeof(MDRawContextSPARC);
return false;
}
scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_sparc->context_flags = context_flags;
size_t flags_size = sizeof(context_sparc->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextSPARC) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read sparc context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext sparc does not match system info";
return false;
}
if (minidump_->swap()) {
// context_sparc->context_flags was already swapped.
for (unsigned int gpr_index = 0;
gpr_index < MD_CONTEXT_SPARC_GPR_COUNT;
++gpr_index) {
Swap(&context_sparc->g_r[gpr_index]);
}
Swap(&context_sparc->ccr);
Swap(&context_sparc->pc);
Swap(&context_sparc->npc);
Swap(&context_sparc->y);
Swap(&context_sparc->asi);
Swap(&context_sparc->fprs);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT;
++fpr_index) {
Swap(&context_sparc->float_save.regs[fpr_index]);
}
Swap(&context_sparc->float_save.filler);
Swap(&context_sparc->float_save.fsr);
}
SetContextSPARC(context_sparc.release());
break;
}
case MD_CONTEXT_ARM: {
if (expected_size != sizeof(MDRawContextARM)) {
BPLOG(ERROR) << "MinidumpContext arm size mismatch, " <<
expected_size << " != " << sizeof(MDRawContextARM);
return false;
}
scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_arm->context_flags = context_flags;
size_t flags_size = sizeof(context_arm->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextARM) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read arm context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext arm does not match system info";
return false;
}
if (minidump_->swap()) {
// context_arm->context_flags was already swapped.
for (unsigned int ireg_index = 0;
ireg_index < MD_CONTEXT_ARM_GPR_COUNT;
++ireg_index) {
Swap(&context_arm->iregs[ireg_index]);
}
Swap(&context_arm->cpsr);
Swap(&context_arm->float_save.fpscr);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT;
++fpr_index) {
Swap(&context_arm->float_save.regs[fpr_index]);
}
for (unsigned int fpe_index = 0;
fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT;
++fpe_index) {
Swap(&context_arm->float_save.extra[fpe_index]);
}
}
SetContextARM(context_arm.release());
break;
}
case MD_CONTEXT_ARM64: {
if (expected_size != sizeof(MDRawContextARM64)) {
BPLOG(ERROR) << "MinidumpContext arm64 size mismatch, " <<
expected_size << " != " << sizeof(MDRawContextARM64);
return false;
}
scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_arm64->context_flags = context_flags;
size_t flags_size = sizeof(context_arm64->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(*context_arm64) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read arm64 context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext arm does not match system info";
return false;
}
if (minidump_->swap()) {
// context_arm64->context_flags was already swapped.
for (unsigned int ireg_index = 0;
ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
++ireg_index) {
Swap(&context_arm64->iregs[ireg_index]);
}
Swap(&context_arm64->cpsr);
Swap(&context_arm64->float_save.fpsr);
Swap(&context_arm64->float_save.fpcr);
for (unsigned int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT;
++fpr_index) {
Normalize128(&context_arm64->float_save.regs[fpr_index],
minidump_->is_big_endian());
Swap(&context_arm64->float_save.regs[fpr_index]);
}
}
SetContextARM64(context_arm64.release());
break;
}
case MD_CONTEXT_MIPS:
case MD_CONTEXT_MIPS64: {
if (expected_size != sizeof(MDRawContextMIPS)) {
BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, "
<< expected_size
<< " != "
<< sizeof(MDRawContextMIPS);
return false;
}
scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS());
// Set the context_flags member, which has already been read, and
// read the rest of the structure beginning with the first member
// after context_flags.
context_mips->context_flags = context_flags;
size_t flags_size = sizeof(context_mips->context_flags);
uint8_t* context_after_flags =
reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size;
if (!minidump_->ReadBytes(context_after_flags,
sizeof(MDRawContextMIPS) - flags_size)) {
BPLOG(ERROR) << "MinidumpContext could not read MIPS context";
return false;
}
// Do this after reading the entire MDRawContext structure because
// GetSystemInfo may seek minidump to a new position.
if (!CheckAgainstSystemInfo(cpu_type)) {
BPLOG(ERROR) << "MinidumpContext MIPS does not match system info";
return false;
}
if (minidump_->swap()) {
// context_mips->context_flags was already swapped.
for (int ireg_index = 0;
ireg_index < MD_CONTEXT_MIPS_GPR_COUNT;
++ireg_index) {
Swap(&context_mips->iregs[ireg_index]);
}
Swap(&context_mips->mdhi);
Swap(&context_mips->mdlo);
for (int dsp_index = 0;
dsp_index < MD_CONTEXT_MIPS_DSP_COUNT;
++dsp_index) {
Swap(&context_mips->hi[dsp_index]);
Swap(&context_mips->lo[dsp_index]);
}
Swap(&context_mips->dsp_control);
Swap(&context_mips->epc);
Swap(&context_mips->badvaddr);
Swap(&context_mips->status);
Swap(&context_mips->cause);
for (int fpr_index = 0;
fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT;
++fpr_index) {
Swap(&context_mips->float_save.regs[fpr_index]);
}
Swap(&context_mips->float_save.fpcsr);
Swap(&context_mips->float_save.fir);
}
SetContextMIPS(context_mips.release());
break;
}
default: {
// Unknown context type - Don't log as an error yet. Let the
// caller work that out.
BPLOG(INFO) << "MinidumpContext unknown context type " <<
HexString(cpu_type);
return false;
break;
}
}
SetContextFlags(context_flags);
}
valid_ = true;
return true;
}