aboutsummaryrefslogtreecommitdiff
path: root/src/processor/minidump.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor/minidump.cc')
-rw-r--r--src/processor/minidump.cc83
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";