From 8c33b3e9c95a67a9bb06c033d5d4c28d9a55168b Mon Sep 17 00:00:00 2001 From: "ted.mielczarek" Date: Fri, 1 Oct 2010 13:01:57 +0000 Subject: Refactor some bits of StackWalkerX86 / StackFrameX86 out into their respective parent classes so they can be used by other architecture implementations. R=jimb at http://breakpad.appspot.com/205001/show git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@703 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/google_breakpad/processor/stack_frame.h | 39 ++++++++++++++++++++++++- src/google_breakpad/processor/stack_frame_cpu.h | 18 ------------ src/google_breakpad/processor/stackwalker.h | 37 +++++++++++++++++++++-- 3 files changed, 73 insertions(+), 21 deletions(-) (limited to 'src/google_breakpad/processor') diff --git a/src/google_breakpad/processor/stack_frame.h b/src/google_breakpad/processor/stack_frame.h index b330f8ae..a47c621f 100644 --- a/src/google_breakpad/processor/stack_frame.h +++ b/src/google_breakpad/processor/stack_frame.h @@ -40,6 +40,19 @@ class CodeModule; using std::string; struct StackFrame { + // Indicates how well the instruction pointer derived during + // stack walking is trusted. Since the stack walker can resort to + // stack scanning, it can wind up with dubious frames. + // In rough order of "trust metric". + enum FrameTrust { + FRAME_TRUST_NONE, // Unknown + FRAME_TRUST_SCAN, // Scanned the stack, found this + FRAME_TRUST_CFI_SCAN, // Scanned the stack using call frame info, found this + FRAME_TRUST_FP, // Derived from frame pointer + FRAME_TRUST_CFI, // Derived from call frame info + FRAME_TRUST_CONTEXT // Given as instruction pointer in a context + }; + StackFrame() : instruction(), module(NULL), @@ -47,9 +60,29 @@ struct StackFrame { function_base(), source_file_name(), source_line(), - source_line_base() {} + source_line_base(), + trust(FRAME_TRUST_NONE) {} virtual ~StackFrame() {} + // Return a string describing how this stack frame was found + // by the stackwalker. + string trust_description() const { + switch (trust) { + case StackFrame::FRAME_TRUST_NONE: + return "unknown"; + case StackFrame::FRAME_TRUST_CONTEXT: + return "given as instruction pointer in context"; + case StackFrame::FRAME_TRUST_CFI: + return "call frame info"; + case StackFrame::FRAME_TRUST_CFI_SCAN: + return "call frame info with scanning"; + case StackFrame::FRAME_TRUST_FP: + return "previous frame's frame pointer"; + case StackFrame::FRAME_TRUST_SCAN: + return "stack scanning"; + } + }; + // The program counter location as an absolute virtual address. For the // innermost called frame in a stack, this will be an exact program counter // or instruction pointer value. For all other frames, this will be within @@ -77,6 +110,10 @@ struct StackFrame { // The start address of the source line, may be omitted if debug symbols // are not available. u_int64_t source_line_base; + + // Amount of trust the stack walker has in the instruction pointer + // of this frame. + FrameTrust trust; }; } // namespace google_breakpad diff --git a/src/google_breakpad/processor/stack_frame_cpu.h b/src/google_breakpad/processor/stack_frame_cpu.h index 0996886f..805b6bc3 100644 --- a/src/google_breakpad/processor/stack_frame_cpu.h +++ b/src/google_breakpad/processor/stack_frame_cpu.h @@ -70,23 +70,9 @@ struct StackFrameX86 : public StackFrame { CONTEXT_VALID_ALL = -1 }; - // Indicates how well we trust the instruction pointer we derived - // during stack walking. Since the stack walker can resort to - // stack scanning, we can wind up with dubious frames. - // In rough order of "trust metric". - enum FrameTrust { - FRAME_TRUST_NONE, // Unknown - FRAME_TRUST_SCAN, // Scanned the stack, found this - FRAME_TRUST_CFI_SCAN, // Scanned the stack using call frame info, found this - FRAME_TRUST_FP, // Derived from frame pointer - FRAME_TRUST_CFI, // Derived from call frame info - FRAME_TRUST_CONTEXT // Given as instruction pointer in a context - }; - StackFrameX86() : context(), context_validity(CONTEXT_VALID_NONE), - trust(FRAME_TRUST_NONE), windows_frame_info(NULL), cfi_frame_info(NULL) {} ~StackFrameX86(); @@ -101,10 +87,6 @@ struct StackFrameX86 : public StackFrame { // the OR operator doesn't work well with enumerated types. This indicates // which fields in context are valid. int context_validity; - - // Amount of trust the stack walker has in the instruction pointer - // of this frame. - FrameTrust trust; // Any stack walking information we found describing this.instruction. // These may be NULL if there is no such information for that address. diff --git a/src/google_breakpad/processor/stackwalker.h b/src/google_breakpad/processor/stackwalker.h index 36d721d1..8dd2a971 100644 --- a/src/google_breakpad/processor/stackwalker.h +++ b/src/google_breakpad/processor/stackwalker.h @@ -44,12 +44,12 @@ #include #include #include "google_breakpad/common/breakpad_types.h" +#include "google_breakpad/processor/code_modules.h" +#include "google_breakpad/processor/memory_region.h" namespace google_breakpad { class CallStack; -class CodeModules; -class MemoryRegion; class MinidumpContext; class SourceLineResolverInterface; struct StackFrame; @@ -108,6 +108,39 @@ class Stackwalker { // Returns false otherwise. bool InstructionAddressSeemsValid(u_int64_t address); + // Scan the stack starting at location_start, looking for an address + // that looks like a valid instruction pointer. Addresses must + // 1) be contained in the current stack memory + // 2) pass the checks in InstructionAddressSeemsValid + // + // Returns true if a valid-looking instruction pointer was found. + // When returning true, sets location_found to the address at which + // the value was found, and ip_found to the value contained at that + // location in memory. + template + bool ScanForReturnAddress(InstructionType location_start, + InstructionType *location_found, + InstructionType *ip_found) { + const int kRASearchWords = 15; + for (InstructionType location = location_start; + location <= location_start + kRASearchWords * sizeof(InstructionType); + location += sizeof(InstructionType)) { + InstructionType ip; + if (!memory_->GetMemoryAtAddress(location, &ip)) + break; + + if (modules_ && modules_->GetModuleForAddress(ip) && + InstructionAddressSeemsValid(ip)) { + + *ip_found = ip; + *location_found = location; + return true; + } + } + // nothing found + return false; + } + // Information about the system that produced the minidump. Subclasses // and the SymbolSupplier may find this information useful. const SystemInfo *system_info_; -- cgit v1.2.1