aboutsummaryrefslogtreecommitdiff
path: root/src/processor
diff options
context:
space:
mode:
Diffstat (limited to 'src/processor')
-rw-r--r--src/processor/convert_old_arm64_context.cc67
-rw-r--r--src/processor/convert_old_arm64_context.h42
-rw-r--r--src/processor/dump_context.cc25
-rw-r--r--src/processor/microdump.cc22
-rw-r--r--src/processor/minidump.cc83
-rw-r--r--src/processor/processor.gyp2
-rw-r--r--src/processor/stackwalker.cc2
-rw-r--r--src/processor/stackwalker_arm64.cc2
-rw-r--r--src/processor/stackwalker_arm64.h4
-rw-r--r--src/processor/stackwalker_arm64_unittest.cc6
10 files changed, 222 insertions, 33 deletions
diff --git a/src/processor/convert_old_arm64_context.cc b/src/processor/convert_old_arm64_context.cc
new file mode 100644
index 00000000..d4b749e7
--- /dev/null
+++ b/src/processor/convert_old_arm64_context.cc
@@ -0,0 +1,67 @@
+// Copyright (c) 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "processor/convert_old_arm64_context.h"
+
+#include <string.h>
+
+namespace google_breakpad {
+
+void ConvertOldARM64Context(const MDRawContextARM64_Old& old,
+ MDRawContextARM64* context) {
+ context->context_flags = MD_CONTEXT_ARM64;
+ if (old.context_flags & MD_CONTEXT_ARM64_INTEGER_OLD) {
+ context->context_flags |=
+ MD_CONTEXT_ARM64_INTEGER | MD_CONTEXT_ARM64_CONTROL;
+ }
+ if (old.context_flags & MD_CONTEXT_ARM64_FLOATING_POINT_OLD) {
+ context->context_flags |= MD_CONTEXT_ARM64_FLOATING_POINT;
+ }
+
+ context->cpsr = old.cpsr;
+
+ static_assert(sizeof(old.iregs) == sizeof(context->iregs),
+ "iregs size mismatch");
+ memcpy(context->iregs, old.iregs, sizeof(context->iregs));
+
+ static_assert(sizeof(old.float_save.regs) == sizeof(context->float_save.regs),
+ "float_save.regs size mismatch");
+ memcpy(context->float_save.regs,
+ old.float_save.regs,
+ sizeof(context->float_save.regs));
+ context->float_save.fpcr = old.float_save.fpcr;
+ context->float_save.fpsr = old.float_save.fpsr;
+
+ memset(context->bcr, 0, sizeof(context->bcr));
+ memset(context->bvr, 0, sizeof(context->bvr));
+ memset(context->wcr, 0, sizeof(context->wcr));
+ memset(context->wvr, 0, sizeof(context->wvr));
+}
+
+} // namespace google_breakpad
diff --git a/src/processor/convert_old_arm64_context.h b/src/processor/convert_old_arm64_context.h
new file mode 100644
index 00000000..8c0dfe90
--- /dev/null
+++ b/src/processor/convert_old_arm64_context.h
@@ -0,0 +1,42 @@
+// Copyright (c) 2018, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
+#define PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
+
+#include "google_breakpad/common/minidump_cpu_arm64.h"
+
+namespace google_breakpad {
+
+void ConvertOldARM64Context(const MDRawContextARM64_Old& old,
+ MDRawContextARM64* context);
+
+} // namespace google_breakpad
+
+#endif // PROCESSOR_CONVERT_OLD_ARM64_CONTEXT_H__
diff --git a/src/processor/dump_context.cc b/src/processor/dump_context.cc
index 198b9501..63ccf4ab 100644
--- a/src/processor/dump_context.cc
+++ b/src/processor/dump_context.cc
@@ -121,13 +121,13 @@ const MDRawContextARM* DumpContext::GetContextARM() const {
return context_.arm;
}
-const MDRawContextARM64_Old* DumpContext::GetContextARM64() const {
- if (GetContextCPU() != MD_CONTEXT_ARM64_OLD) {
+const MDRawContextARM64* DumpContext::GetContextARM64() const {
+ if (GetContextCPU() != MD_CONTEXT_ARM64) {
BPLOG(ERROR) << "DumpContext cannot get arm64 context";
return NULL;
}
- return context_.arm64_old;
+ return context_.arm64;
}
const MDRawContextMIPS* DumpContext::GetContextMIPS() const {
@@ -157,7 +157,7 @@ bool DumpContext::GetInstructionPointer(uint64_t* ip) const {
case MD_CONTEXT_ARM:
*ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC];
break;
- case MD_CONTEXT_ARM64_OLD:
+ case MD_CONTEXT_ARM64:
*ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC];
break;
case MD_CONTEXT_PPC:
@@ -201,7 +201,7 @@ bool DumpContext::GetStackPointer(uint64_t* sp) const {
case MD_CONTEXT_ARM:
*sp = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_SP];
break;
- case MD_CONTEXT_ARM64_OLD:
+ case MD_CONTEXT_ARM64:
*sp = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_SP];
break;
case MD_CONTEXT_PPC:
@@ -256,8 +256,8 @@ void DumpContext::SetContextARM(MDRawContextARM* arm) {
context_.arm = arm;
}
-void DumpContext::SetContextARM64(MDRawContextARM64_Old* arm64) {
- context_.arm64_old = arm64;
+void DumpContext::SetContextARM64(MDRawContextARM64* arm64) {
+ context_.arm64 = arm64;
}
void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) {
@@ -290,10 +290,6 @@ void DumpContext::FreeContext() {
delete context_.arm;
break;
- case MD_CONTEXT_ARM64_OLD:
- delete context_.arm64_old;
- break;
-
case MD_CONTEXT_MIPS:
case MD_CONTEXT_MIPS64:
delete context_.ctx_mips;
@@ -581,10 +577,10 @@ void DumpContext::Print() {
break;
}
- case MD_CONTEXT_ARM64_OLD: {
- const MDRawContextARM64_Old* context_arm64 = GetContextARM64();
+ case MD_CONTEXT_ARM64: {
+ const MDRawContextARM64* context_arm64 = GetContextARM64();
printf("MDRawContextARM64\n");
- printf(" context_flags = 0x%" PRIx64 "\n",
+ printf(" context_flags = 0x%x\n",
context_arm64->context_flags);
for (unsigned int ireg_index = 0;
ireg_index < MD_CONTEXT_ARM64_GPR_COUNT;
@@ -603,6 +599,7 @@ void DumpContext::Print() {
printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n",
freg_index, fp_value.high, fp_value.low);
}
+
break;
}
diff --git a/src/processor/microdump.cc b/src/processor/microdump.cc
index b100f765..13e261b4 100644
--- a/src/processor/microdump.cc
+++ b/src/processor/microdump.cc
@@ -44,6 +44,7 @@
#include "google_breakpad/common/minidump_cpu_arm.h"
#include "google_breakpad/processor/code_module.h"
#include "processor/basic_code_module.h"
+#include "processor/convert_old_arm64_context.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
#include "processor/range_map-inl.h"
@@ -125,8 +126,8 @@ void MicrodumpContext::SetContextARM(MDRawContextARM* arm) {
valid_ = true;
}
-void MicrodumpContext::SetContextARM64(MDRawContextARM64_Old* arm64) {
- DumpContext::SetContextFlags(MD_CONTEXT_ARM64_OLD);
+void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) {
+ DumpContext::SetContextFlags(MD_CONTEXT_ARM64);
DumpContext::SetContextARM64(arm64);
valid_ = true;
}
@@ -311,15 +312,22 @@ Microdump::Microdump(const string& contents)
memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
context_->SetContextARM(arm);
} else if (strcmp(arch.c_str(), kArm64Architecture) == 0) {
- if (cpu_state_raw.size() != sizeof(MDRawContextARM64_Old)) {
+ if (cpu_state_raw.size() == sizeof(MDRawContextARM64)) {
+ MDRawContextARM64* arm = new MDRawContextARM64();
+ memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
+ context_->SetContextARM64(arm);
+ } else if (cpu_state_raw.size() == sizeof(MDRawContextARM64_Old)) {
+ MDRawContextARM64_Old old_arm;
+ memcpy(&old_arm, &cpu_state_raw[0], cpu_state_raw.size());
+ MDRawContextARM64* new_arm = new MDRawContextARM64();
+ ConvertOldARM64Context(old_arm, new_arm);
+ context_->SetContextARM64(new_arm);
+ } else {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
- << " bytes instead of " << sizeof(MDRawContextARM64_Old)
+ << " bytes instead of " << sizeof(MDRawContextARM64)
<< std::endl;
continue;
}
- MDRawContextARM64_Old* arm = new MDRawContextARM64_Old();
- memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size());
- context_->SetContextARM64(arm);
} else if (strcmp(arch.c_str(), kX86Architecture) == 0) {
if (cpu_state_raw.size() != sizeof(MDRawContextX86)) {
std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size()
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";
diff --git a/src/processor/processor.gyp b/src/processor/processor.gyp
index d09a8953..feec7443 100644
--- a/src/processor/processor.gyp
+++ b/src/processor/processor.gyp
@@ -49,6 +49,8 @@
'cfi_frame_info.h',
'contained_range_map-inl.h',
'contained_range_map.h',
+ 'convert_old_arm64_context.cc',
+ 'convert_old_arm64_context.h',
'disassembler_x86.cc',
'disassembler_x86.h',
'dump_context.cc',
diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc
index c7634ff0..4988ef1e 100644
--- a/src/processor/stackwalker.cc
+++ b/src/processor/stackwalker.cc
@@ -259,7 +259,7 @@ Stackwalker* Stackwalker::StackwalkerForCPU(
break;
}
- case MD_CONTEXT_ARM64_OLD:
+ case MD_CONTEXT_ARM64:
cpu_stackwalker = new StackwalkerARM64(system_info,
context->GetContextARM64(),
memory, modules,
diff --git a/src/processor/stackwalker_arm64.cc b/src/processor/stackwalker_arm64.cc
index 042fd089..f9660112 100644
--- a/src/processor/stackwalker_arm64.cc
+++ b/src/processor/stackwalker_arm64.cc
@@ -48,7 +48,7 @@ namespace google_breakpad {
StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info,
- const MDRawContextARM64_Old* context,
+ const MDRawContextARM64* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
diff --git a/src/processor/stackwalker_arm64.h b/src/processor/stackwalker_arm64.h
index 1b01f21e..121e8246 100644
--- a/src/processor/stackwalker_arm64.h
+++ b/src/processor/stackwalker_arm64.h
@@ -55,7 +55,7 @@ class StackwalkerARM64 : public Stackwalker {
// included in the stack. The other arguments are passed directly through
// to the base Stackwalker constructor.
StackwalkerARM64(const SystemInfo* system_info,
- const MDRawContextARM64_Old* context,
+ const MDRawContextARM64* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
@@ -89,7 +89,7 @@ class StackwalkerARM64 : public Stackwalker {
// Stores the CPU context corresponding to the youngest stack frame, to
// be returned by GetContextFrame.
- const MDRawContextARM64_Old* context_;
+ const MDRawContextARM64* context_;
// Validity mask for youngest stack frame. This is always
// CONTEXT_VALID_ALL in real use; it is only changeable for the sake of
diff --git a/src/processor/stackwalker_arm64_unittest.cc b/src/processor/stackwalker_arm64_unittest.cc
index fff70744..f9d18cea 100644
--- a/src/processor/stackwalker_arm64_unittest.cc
+++ b/src/processor/stackwalker_arm64_unittest.cc
@@ -122,14 +122,14 @@ class StackwalkerARM64Fixture {
}
// Fill RAW_CONTEXT with pseudo-random data, for round-trip checking.
- void BrandContext(MDRawContextARM64_Old *raw_context) {
+ void BrandContext(MDRawContextARM64 *raw_context) {
uint8_t x = 173;
for (size_t i = 0; i < sizeof(*raw_context); i++)
reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17);
}
SystemInfo system_info;
- MDRawContextARM64_Old raw_context;
+ MDRawContextARM64 raw_context;
Section stack_section;
MockMemoryRegion stack_region;
MockCodeModule module1;
@@ -688,7 +688,7 @@ struct CFIFixture: public StackwalkerARM64Fixture {
}
// The values we expect to find for the caller's registers.
- MDRawContextARM64_Old expected;
+ MDRawContextARM64 expected;
// The validity mask for expected.
uint64_t expected_validity;