diff options
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r-- | src/processor/minidump.cc | 83 |
1 files changed, 78 insertions, 5 deletions
diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 020b95d3..c86a813f 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -59,6 +59,7 @@ #include "google_breakpad/processor/dump_context.h" #include "processor/basic_code_module.h" #include "processor/basic_code_modules.h" +#include "processor/convert_old_arm64_context.h" #include "processor/logging.h" // All intentional fallthroughs in breakpad are in this file, so define @@ -104,6 +105,8 @@ bool IsContextSizeUnique(uint32_t context_size) { num_matching_contexts++; if (context_size == sizeof(MDRawContextARM)) num_matching_contexts++; + if (context_size == sizeof(MDRawContextARM64)) + num_matching_contexts++; if (context_size == sizeof(MDRawContextARM64_Old)) num_matching_contexts++; if (context_size == sizeof(MDRawContextMIPS)) @@ -745,10 +748,8 @@ bool MinidumpContext::Read(uint32_t expected_size) { for (unsigned int fpr_index = 0; fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; ++fpr_index) { - // While ARM64 is bi-endian, iOS (currently the only platform - // for which ARM64 support has been brought up) uses ARM64 exclusively - // in little-endian mode. - Normalize128(&context_arm64->float_save.regs[fpr_index], false); + Normalize128(&context_arm64->float_save.regs[fpr_index], + minidump_->is_big_endian()); Swap(&context_arm64->float_save.regs[fpr_index]); } } @@ -762,7 +763,9 @@ bool MinidumpContext::Read(uint32_t expected_size) { return false; } - SetContextARM64(context_arm64.release()); + scoped_ptr<MDRawContextARM64> new_context(new MDRawContextARM64()); + ConvertOldARM64Context(*context_arm64.get(), new_context.get()); + SetContextARM64(new_context.release()); } else { uint32_t context_flags; if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { @@ -1059,6 +1062,58 @@ bool MinidumpContext::Read(uint32_t expected_size) { 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)) { @@ -1199,6 +1254,11 @@ bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { return_value = true; break; + case MD_CONTEXT_ARM64: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64) + return_value = true; + break; + case MD_CONTEXT_ARM64_OLD: if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64_OLD) return_value = true; @@ -3487,6 +3547,7 @@ string MinidumpSystemInfo::GetCPU() { cpu = "arm"; break; + case MD_CPU_ARCHITECTURE_ARM64: case MD_CPU_ARCHITECTURE_ARM64_OLD: cpu = "arm64"; break; @@ -4994,6 +5055,7 @@ Minidump::Minidump(const string& path, bool hexdump, unsigned int hexdump_width) path_(path), stream_(NULL), swap_(false), + is_big_endian_(false), valid_(false), hexdump_(hexdump), hexdump_width_(hexdump_width) { @@ -5006,6 +5068,7 @@ Minidump::Minidump(istream& stream) path_(), stream_(&stream), swap_(false), + is_big_endian_(false), valid_(false), hexdump_(false), hexdump_width_(0) { @@ -5086,6 +5149,9 @@ bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) { case MD_CPU_ARCHITECTURE_ARM: *context_cpu_flags = MD_CONTEXT_ARM; break; + case MD_CPU_ARCHITECTURE_ARM64: + *context_cpu_flags = MD_CONTEXT_ARM64; + break; case MD_CPU_ARCHITECTURE_ARM64_OLD: *context_cpu_flags = MD_CONTEXT_ARM64_OLD; break; @@ -5161,6 +5227,13 @@ bool Minidump::Read() { swap_ = false; } +#if defined(__BIG_ENDIAN__) || \ + (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + is_big_endian_ = !swap_; +#else + is_big_endian_ = swap_; +#endif + BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") << "byte-swapping minidump"; |