diff options
author | Joshua Peraza <jperaza@chromium.org> | 2018-08-01 10:48:27 -0700 |
---|---|---|
committer | Joshua Peraza <jperaza@chromium.org> | 2018-08-01 19:27:25 +0000 |
commit | 88d8114fda3e4a7292654bd6ac0c34d6c88a8121 (patch) | |
tree | 7e7c5e65771736eb81e2bef56269eea0cba6953d /src | |
parent | Rename MDRawContextARM64 and its context flags (diff) | |
download | breakpad-88d8114fda3e4a7292654bd6ac0c34d6c88a8121.tar.xz |
Define and use a a new MDRawContextARM64
This struct matches the layout defined by Microsoft and replaces
Breakpad's MDRawContextARM64_Old. This CL updates the processor to
understand either the old or new structs, but clients continue to write
the old structs.
Change-Id: I8dedd9ddb2ec083b802723b9ac87beb18d98edbd
Reviewed-on: https://chromium-review.googlesource.com/1155938
Reviewed-by: Mark Mentovai <mark@chromium.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/client/mac/Breakpad.xcodeproj/project.pbxproj | 10 | ||||
-rw-r--r-- | src/google_breakpad/common/minidump_cpu_arm64.h | 56 | ||||
-rw-r--r-- | src/google_breakpad/common/minidump_format.h | 1 | ||||
-rw-r--r-- | src/google_breakpad/processor/dump_context.h | 6 | ||||
-rw-r--r-- | src/google_breakpad/processor/microdump.h | 2 | ||||
-rw-r--r-- | src/google_breakpad/processor/minidump.h | 5 | ||||
-rw-r--r-- | src/google_breakpad/processor/stack_frame_cpu.h | 2 | ||||
-rw-r--r-- | src/processor/convert_old_arm64_context.cc | 67 | ||||
-rw-r--r-- | src/processor/convert_old_arm64_context.h | 42 | ||||
-rw-r--r-- | src/processor/dump_context.cc | 25 | ||||
-rw-r--r-- | src/processor/microdump.cc | 22 | ||||
-rw-r--r-- | src/processor/minidump.cc | 83 | ||||
-rw-r--r-- | src/processor/processor.gyp | 2 | ||||
-rw-r--r-- | src/processor/stackwalker.cc | 2 | ||||
-rw-r--r-- | src/processor/stackwalker_arm64.cc | 2 | ||||
-rw-r--r-- | src/processor/stackwalker_arm64.h | 4 | ||||
-rw-r--r-- | src/processor/stackwalker_arm64_unittest.cc | 6 | ||||
-rw-r--r-- | src/tools/linux/md2core/minidump-2-core.cc | 33 | ||||
-rw-r--r-- | src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj | 6 |
19 files changed, 325 insertions, 51 deletions
diff --git a/src/client/mac/Breakpad.xcodeproj/project.pbxproj b/src/client/mac/Breakpad.xcodeproj/project.pbxproj index 57e0d1ab..2d30ed6c 100644 --- a/src/client/mac/Breakpad.xcodeproj/project.pbxproj +++ b/src/client/mac/Breakpad.xcodeproj/project.pbxproj @@ -52,6 +52,9 @@ 3329D4ED0FA16D820007BBC5 /* Breakpad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3329D4EC0FA16D820007BBC5 /* Breakpad.xib */; }; 33880C800F9E097100817F82 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 33880C7E0F9E097100817F82 /* InfoPlist.strings */; }; 4084699D0F5D9CF900FDCA37 /* crash_report_sender.icns in Resources */ = {isa = PBXBuildFile; fileRef = 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */; }; + 421BC5BC21110C0300B8042E /* convert_old_arm64_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 421BC5AD21110C0300B8042E /* convert_old_arm64_context.cc */; }; + 421BC5BD21110C0300B8042E /* convert_old_arm64_context.h in Headers */ = {isa = PBXBuildFile; fileRef = 421BC5BB21110C0300B8042E /* convert_old_arm64_context.h */; }; + 421BC5BE21110C1000B8042E /* convert_old_arm64_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 421BC5AD21110C0300B8042E /* convert_old_arm64_context.cc */; }; 4247E6412110D7A300482558 /* memory_allocator_unittest.cc in Sources */ = {isa = PBXBuildFile; fileRef = D244540A12439BA0009BBCE0 /* memory_allocator_unittest.cc */; }; 4D61A25F14F43CFC002D5862 /* bootstrap_compat.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D61A25D14F43CFC002D5862 /* bootstrap_compat.cc */; }; 4D61A26B14F43D3C002D5862 /* bootstrap_compat.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D61A25D14F43CFC002D5862 /* bootstrap_compat.cc */; }; @@ -577,6 +580,8 @@ 3329D4EC0FA16D820007BBC5 /* Breakpad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Breakpad.xib; path = sender/Breakpad.xib; sourceTree = "<group>"; }; 33880C7F0F9E097100817F82 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = sender/English.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 4084699C0F5D9CF900FDCA37 /* crash_report_sender.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = crash_report_sender.icns; path = sender/crash_report_sender.icns; sourceTree = "<group>"; }; + 421BC5AD21110C0300B8042E /* convert_old_arm64_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = convert_old_arm64_context.cc; path = ../../processor/convert_old_arm64_context.cc; sourceTree = "<group>"; }; + 421BC5BB21110C0300B8042E /* convert_old_arm64_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convert_old_arm64_context.h; path = ../../processor/convert_old_arm64_context.h; sourceTree = "<group>"; }; 4D61A25D14F43CFC002D5862 /* bootstrap_compat.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bootstrap_compat.cc; path = ../../common/mac/bootstrap_compat.cc; sourceTree = SOURCE_ROOT; }; 4D61A25E14F43CFC002D5862 /* bootstrap_compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = bootstrap_compat.h; path = ../../common/mac/bootstrap_compat.h; sourceTree = SOURCE_ROOT; }; 4D72CA0D13DFAD5C006CABE3 /* md5.cc */ = {isa = PBXFileReference; explicitFileType = sourcecode.cpp.cpp; fileEncoding = 4; name = md5.cc; path = ../../common/md5.cc; sourceTree = SOURCE_ROOT; }; @@ -896,6 +901,8 @@ D244536912426EE7009BBCE0 /* processor */ = { isa = PBXGroup; children = ( + 421BC5AD21110C0300B8042E /* convert_old_arm64_context.cc */, + 421BC5BB21110C0300B8042E /* convert_old_arm64_context.h */, D244535112426EBB009BBCE0 /* logging.cc */, D244535212426EBB009BBCE0 /* minidump.cc */, D244535312426EBB009BBCE0 /* pathname_stripper.cc */, @@ -1154,6 +1161,7 @@ D2F9A4CC121336C7002747C1 /* crash_generation_server.h in Headers */, 163201D61443019E00C4DBF5 /* ConfigFile.h in Headers */, 16C7C918147D45AE00776EAD /* BreakpadDefines.h in Headers */, + 421BC5BD21110C0300B8042E /* convert_old_arm64_context.h in Headers */, 162F64F3161C577500CD68D5 /* arch_utilities.h in Headers */, F4DAB1DE19F1027100A5A838 /* launch_reporter.h in Headers */, 1EEEB6241720829E00F7E689 /* simple_string_dictionary.h in Headers */, @@ -1686,6 +1694,7 @@ 163201D71443019E00C4DBF5 /* ConfigFile.mm in Sources */, 162F64F2161C577500CD68D5 /* arch_utilities.cc in Sources */, 1EEEB6231720829E00F7E689 /* simple_string_dictionary.cc in Sources */, + 421BC5BC21110C0300B8042E /* convert_old_arm64_context.cc in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1844,6 +1853,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 421BC5BE21110C1000B8042E /* convert_old_arm64_context.cc in Sources */, 4247E6412110D7A300482558 /* memory_allocator_unittest.cc in Sources */, D244536A12426F00009BBCE0 /* logging.cc in Sources */, D244536B12426F00009BBCE0 /* minidump.cc in Sources */, diff --git a/src/google_breakpad/common/minidump_cpu_arm64.h b/src/google_breakpad/common/minidump_cpu_arm64.h index e146ec99..0411bebb 100644 --- a/src/google_breakpad/common/minidump_cpu_arm64.h +++ b/src/google_breakpad/common/minidump_cpu_arm64.h @@ -66,7 +66,61 @@ #ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__ #define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM64_H__ +#include "google_breakpad/common/breakpad_types.h" + #define MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT 32 +#define MD_CONTEXT_ARM64_GPR_COUNT 33 + +typedef struct { + /* 32 128-bit floating point registers, d0 .. d31. */ + uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT]; + + uint32_t fpcr; /* FPU control register */ + uint32_t fpsr; /* FPU status register */ +} MDFloatingSaveAreaARM64; + +/* For (MDRawContextARM64).context_flags. These values indicate the type of + * context stored in the structure. */ +#define MD_CONTEXT_ARM64 0x00400000 +#define MD_CONTEXT_ARM64_CONTROL (MD_CONTEXT_ARM64 | 0x00000001) +#define MD_CONTEXT_ARM64_INTEGER (MD_CONTEXT_ARM64 | 0x00000002) +#define MD_CONTEXT_ARM64_FLOATING_POINT (MD_CONTEXT_ARM64 | 0x00000004) +#define MD_CONTEXT_ARM64_DEBUG (MD_CONTEXT_ARM64 | 0x00000008) +#define MD_CONTEXT_ARM64_FULL (MD_CONTEXT_ARM64_CONTROL | \ + MD_CONTEXT_ARM64_INTEGER | \ + MD_CONTEXT_ARM64_FLOATING_POINT) +#define MD_CONTEXT_ARM64_ALL (MD_CONTEXT_ARM64_FULL | MD_CONTEXT_ARM64_DEBUG) + +typedef struct { + /* Determines which fields of this struct are populated */ + uint32_t context_flags; + + /* CPSR (flags, basically): 32 bits: + bit 31 - N (negative) + bit 30 - Z (zero) + bit 29 - C (carry) + bit 28 - V (overflow) + bit 27 - Q (saturation flag, sticky) + All other fields -- ignore */ + uint32_t cpsr; + + /* 33 64-bit integer registers, x0 .. x31 + the PC + * Note the following fixed uses: + * x29 is the frame pointer + * x30 is the link register + * x31 is the stack pointer + * The PC is effectively x32. + */ + uint64_t iregs[MD_CONTEXT_ARM64_GPR_COUNT]; + + /* The next field is included with MD_CONTEXT64_ARM_FLOATING_POINT */ + MDFloatingSaveAreaARM64 float_save; + + uint32_t bcr[8]; + uint64_t bvr[8]; + uint32_t wcr[2]; + uint64_t wvr[2]; +} MDRawContextARM64; typedef struct { uint32_t fpsr; /* FPU status register */ @@ -76,8 +130,6 @@ typedef struct { uint128_struct regs[MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT]; } MDFloatingSaveAreaARM64_Old; -#define MD_CONTEXT_ARM64_GPR_COUNT 33 - /* Use the same 32-bit alignment when accessing this structure from 64-bit code * as is used natively in 32-bit code. */ #pragma pack(push, 4) diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h index 9db7049a..04c94cd3 100644 --- a/src/google_breakpad/common/minidump_format.h +++ b/src/google_breakpad/common/minidump_format.h @@ -654,6 +654,7 @@ typedef enum { MD_CPU_ARCHITECTURE_AMD64 = 9, /* PROCESSOR_ARCHITECTURE_AMD64 */ MD_CPU_ARCHITECTURE_X86_WIN64 = 10, /* PROCESSOR_ARCHITECTURE_IA32_ON_WIN64 (WoW64) */ + MD_CPU_ARCHITECTURE_ARM64 = 12, /* PROCESSOR_ARCHITECTURE_ARM64 */ MD_CPU_ARCHITECTURE_SPARC = 0x8001, /* Breakpad-defined value for SPARC */ MD_CPU_ARCHITECTURE_PPC64 = 0x8002, /* Breakpad-defined value for PPC64 */ MD_CPU_ARCHITECTURE_ARM64_OLD = 0x8003, /* Breakpad-defined value for ARM64 */ diff --git a/src/google_breakpad/processor/dump_context.h b/src/google_breakpad/processor/dump_context.h index 455115e5..df80bf7e 100644 --- a/src/google_breakpad/processor/dump_context.h +++ b/src/google_breakpad/processor/dump_context.h @@ -56,7 +56,7 @@ class DumpContext : public DumpObject { // context data does not match the CPU type or does not exist, returns NULL. const MDRawContextAMD64* GetContextAMD64() const; const MDRawContextARM* GetContextARM() const; - const MDRawContextARM64_Old* GetContextARM64() const; + const MDRawContextARM64* GetContextARM64() const; const MDRawContextMIPS* GetContextMIPS() const; const MDRawContextPPC* GetContextPPC() const; const MDRawContextPPC64* GetContextPPC64() const; @@ -85,7 +85,7 @@ class DumpContext : public DumpObject { void SetContextAMD64(MDRawContextAMD64* amd64); void SetContextSPARC(MDRawContextSPARC* ctx_sparc); void SetContextARM(MDRawContextARM* arm); - void SetContextARM64(MDRawContextARM64_Old* arm64); + void SetContextARM64(MDRawContextARM64* arm64); void SetContextMIPS(MDRawContextMIPS* ctx_mips); // Free the CPU-specific context structure. @@ -103,7 +103,7 @@ class DumpContext : public DumpObject { // so variables can NOT be named as sparc MDRawContextSPARC* ctx_sparc; MDRawContextARM* arm; - MDRawContextARM64_Old* arm64_old; + MDRawContextARM64* arm64; MDRawContextMIPS* ctx_mips; } context_; diff --git a/src/google_breakpad/processor/microdump.h b/src/google_breakpad/processor/microdump.h index 496f83ce..02ebdcd7 100644 --- a/src/google_breakpad/processor/microdump.h +++ b/src/google_breakpad/processor/microdump.h @@ -68,7 +68,7 @@ class MicrodumpModules : public BasicCodeModules { class MicrodumpContext : public DumpContext { public: virtual void SetContextARM(MDRawContextARM* arm); - virtual void SetContextARM64(MDRawContextARM64_Old* arm64); + virtual void SetContextARM64(MDRawContextARM64* arm64); virtual void SetContextX86(MDRawContextX86* x86); virtual void SetContextMIPS(MDRawContextMIPS* mips32); virtual void SetContextMIPS64(MDRawContextMIPS* mips64); diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h index 1ad513df..febdaeb7 100644 --- a/src/google_breakpad/processor/minidump.h +++ b/src/google_breakpad/processor/minidump.h @@ -1260,6 +1260,8 @@ class Minidump { bool swap() const { return valid_ ? swap_ : false; } + bool is_big_endian() const { return valid_ ? is_big_endian_ : false; } + // Print a human-readable representation of the object to stdout. void Print(); @@ -1325,6 +1327,9 @@ class Minidump { // same-endian, this will be false. bool swap_; + // true if the minidump was produced by a big-endian cpu. + bool is_big_endian_; + // Validity of the Minidump structure, false immediately after // construction or after a failed Read(); true following a successful // Read(). diff --git a/src/google_breakpad/processor/stack_frame_cpu.h b/src/google_breakpad/processor/stack_frame_cpu.h index 3b2551b5..dc5d8ae6 100644 --- a/src/google_breakpad/processor/stack_frame_cpu.h +++ b/src/google_breakpad/processor/stack_frame_cpu.h @@ -327,7 +327,7 @@ struct StackFrameARM64 : public StackFrame { // stack. In other frames, the values of nonvolatile registers may be // present, given sufficient debugging information. Refer to // context_validity. - MDRawContextARM64_Old context; + MDRawContextARM64 context; // For each register in context whose value has been recovered, we set // the corresponding CONTEXT_VALID_ bit in context_validity. 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; diff --git a/src/tools/linux/md2core/minidump-2-core.cc b/src/tools/linux/md2core/minidump-2-core.cc index cf9648f6..941586e9 100644 --- a/src/tools/linux/md2core/minidump-2-core.cc +++ b/src/tools/linux/md2core/minidump-2-core.cc @@ -480,17 +480,28 @@ ParseThreadRegisters(CrashedProcess::Thread* thread, static void ParseThreadRegisters(CrashedProcess::Thread* thread, const MinidumpMemoryRange& range) { - const MDRawContextARM64_Old* rawregs = range.GetData<MDRawContextARM64_Old>(0); - - for (int i = 0; i < 31; ++i) - thread->regs.regs[i] = rawregs->iregs[i]; - thread->regs.sp = rawregs->iregs[MD_CONTEXT_ARM64_REG_SP]; - thread->regs.pc = rawregs->iregs[MD_CONTEXT_ARM64_REG_PC]; - thread->regs.pstate = rawregs->cpsr; - - memcpy(thread->fpregs.vregs, rawregs->float_save.regs, 8 * 32); - thread->fpregs.fpsr = rawregs->float_save.fpsr; - thread->fpregs.fpcr = rawregs->float_save.fpcr; +#define COPY_REGS(rawregs) \ + do { \ + for (int i = 0; i < 31; ++i) \ + thread->regs.regs[i] = rawregs->iregs[i]; \ + thread->regs.sp = rawregs->iregs[MD_CONTEXT_ARM64_REG_SP]; \ + thread->regs.pc = rawregs->iregs[MD_CONTEXT_ARM64_REG_PC]; \ + thread->regs.pstate = rawregs->cpsr; \ + \ + memcpy(thread->fpregs.vregs, rawregs->float_save.regs, 8 * 32); \ + thread->fpregs.fpsr = rawregs->float_save.fpsr; \ + thread->fpregs.fpcr = rawregs->float_save.fpcr; \ + } while (false) + + if (range.length() == sizeof(MDRawContextARM64_Old)) { + const MDRawContextARM64_Old* rawregs = + range.GetData<MDRawContextARM64_Old>(0); + COPY_REGS(rawregs); + } else { + const MDRawContextARM64* rawregs = range.GetData<MDRawContextARM64>(0); + COPY_REGS(rawregs); + } +#undef COPY_REGS } #elif defined(__mips__) static void diff --git a/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj b/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj index ff5eadc0..33204f7e 100644 --- a/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj +++ b/src/tools/mac/crash_report/crash_report.xcodeproj/project.pbxproj @@ -8,6 +8,7 @@ /* Begin PBXBuildFile section */ 162F64FE161C5ECB00CD68D5 /* arch_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */; }; + 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */; }; 4247E6402110D5A500482558 /* path_helper.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4247E63F2110D5A500482558 /* path_helper.cc */; }; 4D2C721B126F9ACC00B43EAF /* source_line_resolver_base.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */; }; 4D2C721F126F9ADE00B43EAF /* exploitability.cc in Sources */ = {isa = PBXBuildFile; fileRef = 4D2C721E126F9ADE00B43EAF /* exploitability.cc */; }; @@ -82,6 +83,8 @@ 08FB779EFE84155DC02AAC07 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 162F64FC161C5ECB00CD68D5 /* arch_utilities.cc */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = arch_utilities.cc; path = ../../../common/mac/arch_utilities.cc; sourceTree = "<group>"; }; 162F64FD161C5ECB00CD68D5 /* arch_utilities.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = arch_utilities.h; path = ../../../common/mac/arch_utilities.h; sourceTree = "<group>"; }; + 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = convert_old_arm64_context.cc; path = ../../../processor/convert_old_arm64_context.cc; sourceTree = "<group>"; }; + 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = convert_old_arm64_context.h; path = ../../../processor/convert_old_arm64_context.h; sourceTree = "<group>"; }; 4247E63E2110D5A500482558 /* path_helper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = path_helper.h; path = ../../../common/path_helper.h; sourceTree = "<group>"; }; 4247E63F2110D5A500482558 /* path_helper.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = path_helper.cc; path = ../../../common/path_helper.cc; sourceTree = "<group>"; }; 4D2C721A126F9ACC00B43EAF /* source_line_resolver_base.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = source_line_resolver_base.cc; path = ../../../processor/source_line_resolver_base.cc; sourceTree = SOURCE_ROOT; }; @@ -218,6 +221,8 @@ 08FB7794FE84155DC02AAC07 /* crash_report */ = { isa = PBXGroup; children = ( + 4214B7FE211109A600B769FA /* convert_old_arm64_context.cc */, + 4214B7FF211109A600B769FA /* convert_old_arm64_context.h */, 4247E63F2110D5A500482558 /* path_helper.cc */, 4247E63E2110D5A500482558 /* path_helper.h */, 8B31025311F0D2D400FCF3E4 /* Breakpad.xcconfig */, @@ -525,6 +530,7 @@ 4D2C7223126F9AF900B43EAF /* exploitability_win.cc in Sources */, 4D2C7227126F9B0F00B43EAF /* disassembler_x86.cc in Sources */, F407DC48185773C10064622B /* exploitability_linux.cc in Sources */, + 4214B800211109A600B769FA /* convert_old_arm64_context.cc in Sources */, 4D2C722B126F9B5A00B43EAF /* x86_disasm.c in Sources */, 4D2C722D126F9B6E00B43EAF /* x86_misc.c in Sources */, 4D2C722F126F9B8300B43EAF /* x86_operand_list.c in Sources */, |