diff --git a/Makefile.am b/Makefile.am index cdeacf15..deb33a90 100644 --- a/Makefile.am +++ b/Makefile.am @@ -95,6 +95,8 @@ src_libbreakpad_la_SOURCES = \ src/processor/stackwalker.cc \ src/processor/stackwalker_amd64.cc \ src/processor/stackwalker_amd64.h \ + src/processor/stackwalker_arm.cc \ + src/processor/stackwalker_arm.h \ src/processor/stackwalker_ppc.cc \ src/processor/stackwalker_ppc.h \ src/processor/stackwalker_sparc.cc \ @@ -172,6 +174,7 @@ src_processor_minidump_processor_unittest_LDADD = \ src/processor/process_state.lo \ src/processor/stackwalker.lo \ src/processor/stackwalker_amd64.lo \ + src/processor/stackwalker_arm.lo \ src/processor/stackwalker_ppc.lo \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo @@ -219,6 +222,7 @@ src_processor_stackwalker_selftest_LDADD = \ src/processor/pathname_stripper.lo \ src/processor/stackwalker.lo \ src/processor/stackwalker_amd64.lo \ + src/processor/stackwalker_arm.lo \ src/processor/stackwalker_ppc.lo \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo @@ -249,6 +253,7 @@ src_processor_minidump_stackwalk_LDADD = \ src/processor/simple_symbol_supplier.lo \ src/processor/stackwalker.lo \ src/processor/stackwalker_amd64.lo \ + src/processor/stackwalker_arm.lo \ src/processor/stackwalker_ppc.lo \ src/processor/stackwalker_sparc.lo \ src/processor/stackwalker_x86.lo diff --git a/src/google_breakpad/common/minidump_cpu_arm.h b/src/google_breakpad/common/minidump_cpu_arm.h new file mode 100644 index 00000000..bd3d934f --- /dev/null +++ b/src/google_breakpad/common/minidump_cpu_arm.h @@ -0,0 +1,130 @@ +/* Copyright (c) 2009, 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. */ + +/* minidump_format.h: A cross-platform reimplementation of minidump-related + * portions of DbgHelp.h from the Windows Platform SDK. + * + * (This is C99 source, please don't corrupt it with C++.) + * + * This file contains the necessary definitions to read minidump files + * produced on ARM. These files may be read on any platform provided + * that the alignments of these structures on the processing system are + * identical to the alignments of these structures on the producing system. + * For this reason, precise-sized types are used. The structures defined + * by this file have been laid out to minimize alignment problems by + * ensuring that all members are aligned on their natural boundaries. + * In some cases, tail-padding may be significant when different ABIs specify + * different tail-padding behaviors. To avoid problems when reading or + * writing affected structures, MD_*_SIZE macros are provided where needed, + * containing the useful size of the structures without padding. + * + * Structures that are defined by Microsoft to contain a zero-length array + * are instead defined here to contain an array with one element, as + * zero-length arrays are forbidden by standard C and C++. In these cases, + * *_minsize constants are provided to be used in place of sizeof. For a + * cleaner interface to these sizes when using C++, see minidump_size.h. + * + * These structures are also sufficient to populate minidump files. + * + * Because precise data type sizes are crucial for this implementation to + * function properly and portably, a set of primitive types with known sizes + * are used as the basis of each structure defined by this file. + * + * Author: Julian Seward + */ + +/* + * ARM support + */ + +#ifndef GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ +#define GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ + +#define MD_FLOATINGSAVEAREA_ARM_FPR_COUNT 32 +#define MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT 8 + +/* + * Note that these structures *do not* map directly to the CONTEXT + * structure defined in WinNT.h in the Windows Mobile SDK. That structure + * does not accomodate VFPv3, and I'm unsure if it was ever used in the + * wild anyway, as Windows CE only seems to produce "cedumps" which + * are not exactly minidumps. + */ +typedef struct { + u_int64_t fpscr; /* FPU status register */ + + /* 32 64-bit floating point registers, d0 .. d31. */ + u_int64_t regs[MD_FLOATINGSAVEAREA_ARM_FPR_COUNT]; + + /* Miscellaneous control words */ + u_int32_t extra[MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT]; +} MDFloatingSaveAreaARM; + +#define MD_CONTEXT_ARM_GPR_COUNT 16 + +typedef struct { + /* The next field determines the layout of the structure, and which parts + * of it are populated + */ + u_int32_t context_flags; + + /* 16 32-bit integer registers, r0 .. r15 + * Note the following fixed uses: + * r13 is the stack pointer + * r14 is the link register + * r15 is the program counter + */ + u_int32_t iregs[MD_CONTEXT_ARM_GPR_COUNT]; + + /* 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 */ + u_int32_t cpsr; + + /* The next field is included with MD_CONTEXT_ARM_FLOATING_POINT */ + MDFloatingSaveAreaARM float_save; + +} MDRawContextARM; + +/* For (MDRawContextARM).context_flags. These values indicate the type of + * context stored in the structure. */ +#define MD_CONTEXT_ARM_INTEGER (MD_CONTEXT_ARM | 0x00000002) +#define MD_CONTEXT_ARM_FLOATING_POINT (MD_CONTEXT_ARM | 0x00000004) + +#define MD_CONTEXT_ARM_FULL (MD_CONTEXT_ARM_INTEGER | \ + MD_CONTEXT_ARM_FLOATING_POINT) + +#define MD_CONTEXT_ARM_ALL (MD_CONTEXT_ARM_INTEGER | \ + MD_CONTEXT_ARM_FLOATING_POINT) + +#endif /* GOOGLE_BREAKPAD_COMMON_MINIDUMP_CPU_ARM_H__ */ diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h index 4d9e767f..f3b4a46b 100644 --- a/src/google_breakpad/common/minidump_format.h +++ b/src/google_breakpad/common/minidump_format.h @@ -112,12 +112,12 @@ typedef struct { u_int32_t context_flags; } MDRawContextBase; -#include "minidump_cpu_sparc.h" -#include "minidump_cpu_x86.h" +#include "minidump_cpu_amd64.h" +#include "minidump_cpu_arm.h" #include "minidump_cpu_ppc.h" #include "minidump_cpu_ppc64.h" -#include "minidump_cpu_amd64.h" - +#include "minidump_cpu_sparc.h" +#include "minidump_cpu_x86.h" /* * WinVer.h diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h index 695a7254..2a83c3f0 100644 --- a/src/google_breakpad/processor/minidump.h +++ b/src/google_breakpad/processor/minidump.h @@ -179,10 +179,11 @@ class MinidumpContext : public MinidumpStream { // Returns raw CPU-specific context data for the named CPU type. If the // context data does not match the CPU type or does not exist, returns // NULL. - const MDRawContextX86* GetContextX86() const; - const MDRawContextPPC* GetContextPPC() const; const MDRawContextAMD64* GetContextAMD64() const; + const MDRawContextARM* GetContextARM() const; + const MDRawContextPPC* GetContextPPC() const; const MDRawContextSPARC* GetContextSPARC() const; + const MDRawContextX86* GetContextX86() const; // Print a human-readable representation of the object to stdout. void Print(); @@ -216,7 +217,8 @@ class MinidumpContext : public MinidumpStream { MDRawContextAMD64* amd64; // on Solaris SPARC, sparc is defined as a numeric constant, // so variables can NOT be named as sparc - MDRawContextSPARC* ctx_sparc; + MDRawContextSPARC* ctx_sparc; + MDRawContextARM* arm; } context_; }; diff --git a/src/google_breakpad/processor/stack_frame_cpu.h b/src/google_breakpad/processor/stack_frame_cpu.h index 3d3003b7..1e414638 100644 --- a/src/google_breakpad/processor/stack_frame_cpu.h +++ b/src/google_breakpad/processor/stack_frame_cpu.h @@ -168,6 +168,33 @@ struct StackFrameSPARC : public StackFrame { int context_validity; }; +struct StackFrameARM : public StackFrame { + // ContextValidity should eventually contain entries for the validity of + // other nonvolatile (callee-save) registers as in + // StackFrameX86::ContextValidity. I suspect this list is sufficient + // for arm stackwalking. + enum ContextValidity { + CONTEXT_VALID_NONE = 0, + CONTEXT_VALID_R13 = 1 << 0, + CONTEXT_VALID_R14 = 1 << 1, + CONTEXT_VALID_R15 = 1 << 2, + CONTEXT_VALID_ALL = -1 + }; + + StackFrameARM() : context(), context_validity(CONTEXT_VALID_NONE) {} + + // Register state. This is only fully valid for the topmost frame in a + // stack. In other frames, the values of nonvolatile registers may be + // present, given sufficient debugging information. Refer to + // context_validity. + MDRawContextARM context; + + // context_validity is actually ContextValidity, but int is used because + // the OR operator doesn't work well with enumerated types. This indicates + // which fields in context are valid. + int context_validity; +}; + } // namespace google_breakpad #endif // GOOGLE_BREAKPAD_PROCESSOR_STACK_FRAME_CPU_H__ diff --git a/src/processor/minidump.cc b/src/processor/minidump.cc index 49118589..771edd64 100644 --- a/src/processor/minidump.cc +++ b/src/processor/minidump.cc @@ -620,6 +620,61 @@ bool MinidumpContext::Read(u_int32_t expected_size) { break; } + case MD_CONTEXT_ARM: { + if (expected_size != sizeof(MDRawContextARM)) { + BPLOG(ERROR) << "MinidumpContext arm size mismatch, " << + expected_size << " != " << sizeof(MDRawContextARM); + return false; + } + + scoped_ptr 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); + u_int8_t* context_after_flags = + reinterpret_cast(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]); + } + } + context_.arm = context_arm.release(); + + break; + } + default: { // Unknown context type - Don't log as an error yet. Let the // caller work that out. @@ -685,6 +740,15 @@ const MDRawContextSPARC* MinidumpContext::GetContextSPARC() const { return context_.ctx_sparc; } +const MDRawContextARM* MinidumpContext::GetContextARM() const { + if (GetContextCPU() != MD_CONTEXT_ARM) { + BPLOG(ERROR) << "MinidumpContext cannot get arm context"; + return NULL; + } + + return context_.arm; +} + void MinidumpContext::FreeContext() { switch (GetContextCPU()) { case MD_CONTEXT_X86: @@ -703,6 +767,10 @@ void MinidumpContext::FreeContext() { delete context_.ctx_sparc; break; + case MD_CONTEXT_ARM: + delete context_.arm; + break; + default: // There is no context record (valid_ is false) or there's a // context record for an unknown CPU (shouldn't happen, only known @@ -762,6 +830,11 @@ bool MinidumpContext::CheckAgainstSystemInfo(u_int32_t context_cpu_type) { if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) return_value = true; break; + + case MD_CONTEXT_ARM: + if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM) + return_value = true; + break; } BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << @@ -967,6 +1040,36 @@ void MinidumpContext::Print() { break; } + case MD_CONTEXT_ARM: { + const MDRawContextARM* context_arm = GetContextARM(); + printf("MDRawContextARM\n"); + printf(" context_flags = 0x%x\n", + context_arm->context_flags); + for (unsigned int ireg_index = 0; + ireg_index < MD_CONTEXT_ARM_GPR_COUNT; + ++ireg_index) { + printf(" iregs[%2d] = 0x%x\n", + ireg_index, context_arm->iregs[ireg_index]); + } + printf(" cpsr = 0x%x\n", context_arm->cpsr); + printf(" float_save.fpscr = 0x%" PRIx64 "\n", + for (unsigned int fpr_index = 0; + fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; + ++fpr_index) { + printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", + fpr_index, context_arm->float_save.regs[fpr_index]); + } + for (unsigned int fpe_index = 0; + fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; + ++fpe_index) { + printf(" float_save.extra[%2d] = 0x%" PRIx64 "\n", + fpe_index, context_arm->float_save.extra[fpe_index]); + } + + context_arm->float_save.fpscr); + break; + } + default: { break; } @@ -2727,8 +2830,8 @@ MinidumpContext* MinidumpException::GetContext() { scoped_ptr context(new MinidumpContext(minidump_)); - // Don't log as an error if we can still fall back on th thread's context - // (which must be possible if we got his far.) + // Don't log as an error if we can still fall back on the thread's context + // (which must be possible if we got this far.) if (!context->Read(exception_.thread_context.data_size)) { BPLOG(INFO) << "MinidumpException cannot read context"; return NULL; @@ -3006,6 +3109,10 @@ string MinidumpSystemInfo::GetCPU() { cpu = "x86"; break; + case MD_CPU_ARCHITECTURE_AMD64: + cpu = "x86-64"; + break; + case MD_CPU_ARCHITECTURE_PPC: cpu = "ppc"; break; @@ -3014,6 +3121,10 @@ string MinidumpSystemInfo::GetCPU() { cpu = "sparc"; break; + case MD_CPU_ARCHITECTURE_ARM: + cpu = "arm"; + break; + default: BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " << HexString(system_info_.processor_architecture); diff --git a/src/processor/minidump_processor.cc b/src/processor/minidump_processor.cc index 24b03e9d..e2b5bd3d 100644 --- a/src/processor/minidump_processor.cc +++ b/src/processor/minidump_processor.cc @@ -308,6 +308,11 @@ bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { break; } + case MD_CPU_ARCHITECTURE_ARM: { + info->cpu = "arm"; + break; + } + default: { // Assign the numeric architecture ID into the CPU string. char cpu_string[7]; diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc index 96ee6db0..c8f0da54 100644 --- a/src/processor/stackwalker.cc +++ b/src/processor/stackwalker.cc @@ -52,6 +52,7 @@ #include "processor/stackwalker_sparc.h" #include "processor/stackwalker_x86.h" #include "processor/stackwalker_amd64.h" +#include "processor/stackwalker_arm.h" namespace google_breakpad { @@ -181,6 +182,13 @@ Stackwalker* Stackwalker::StackwalkerForCPU( memory, modules, supplier, resolver); break; + + case MD_CONTEXT_ARM: + cpu_stackwalker = new StackwalkerARM(system_info, + context->GetContextARM(), + memory, modules, supplier, + resolver); + break; } BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) << diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc new file mode 100644 index 00000000..cf241c86 --- /dev/null +++ b/src/processor/stackwalker_arm.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2009, 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. + +// stackwalker_arm.cc: arm-specific stackwalker. +// +// See stackwalker_arm.h for documentation. +// +// Author: Mark Mentovai, Ted Mielczarek + + +#include "processor/stackwalker_arm.h" +#include "google_breakpad/processor/call_stack.h" +#include "google_breakpad/processor/memory_region.h" +#include "google_breakpad/processor/stack_frame_cpu.h" +#include "processor/logging.h" + +namespace google_breakpad { + + +StackwalkerARM::StackwalkerARM(const SystemInfo *system_info, + const MDRawContextARM *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver) + : Stackwalker(system_info, memory, modules, supplier, resolver), + context_(context) { +} + + +StackFrame* StackwalkerARM::GetContextFrame() { + if (!context_ || !memory_) { + BPLOG(ERROR) << "Can't get context frame without context or memory"; + return NULL; + } + + StackFrameARM *frame = new StackFrameARM(); + + // The instruction pointer is stored directly in a register (r15), so pull it + // straight out of the CPU context structure. + frame->context = *context_; + frame->context_validity = StackFrameARM::CONTEXT_VALID_ALL; + frame->instruction = frame->context.iregs[15]; + + return frame; +} + + +StackFrame* StackwalkerARM::GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info) { + if (!memory_ || !stack) { + BPLOG(ERROR) << "Can't get caller frame without memory or stack"; + return NULL; + } + + StackFrameARM *last_frame = static_cast( + stack->frames()->back()); + + // TODO: Can't actually walk the stack on ARM without the CFI data. + // Implement this when the CFI symbol dumper changes have landed. + return NULL; +} + + +} // namespace google_breakpad diff --git a/src/processor/stackwalker_arm.h b/src/processor/stackwalker_arm.h new file mode 100644 index 00000000..4a4756b4 --- /dev/null +++ b/src/processor/stackwalker_arm.h @@ -0,0 +1,80 @@ +// Copyright (c) 2009, 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. + +// stackwalker_arm.h: arm-specific stackwalker. +// +// Provides stack frames given arm register context and a memory region +// corresponding to an arm stack. +// +// Author: Mark Mentovai, Ted Mielczarek + + +#ifndef PROCESSOR_STACKWALKER_ARM_H__ +#define PROCESSOR_STACKWALKER_ARM_H__ + + +#include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/common/minidump_format.h" +#include "google_breakpad/processor/stackwalker.h" + +namespace google_breakpad { + +class CodeModules; + +class StackwalkerARM : public Stackwalker { + public: + // context is an arm context object that gives access to arm-specific + // register state corresponding to the innermost called frame to be + // included in the stack. The other arguments are passed directly through + // to the base Stackwalker constructor. + StackwalkerARM(const SystemInfo *system_info, + const MDRawContextARM *context, + MemoryRegion *memory, + const CodeModules *modules, + SymbolSupplier *supplier, + SourceLineResolverInterface *resolver); + + private: + // Implementation of Stackwalker, using arm context and stack conventions. + // TODO: currently stubbed out, needs CFI symbol dumper support + virtual StackFrame* GetContextFrame(); + virtual StackFrame* GetCallerFrame( + const CallStack *stack, + const vector< linked_ptr > &stack_frame_info); + + // Stores the CPU context corresponding to the innermost stack frame to + // be returned by GetContextFrame. + const MDRawContextARM *context_; +}; + + +} // namespace google_breakpad + + +#endif // PROCESSOR_STACKWALKER_ARM_H__