Refactor the logic of resolving source line info into helper class.

http://breakpad.appspot.com/459002/


git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1068 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
SiyangXie@gmail.com 2012-10-10 21:41:52 +00:00
parent f72b9c6ff4
commit bab770045b
22 changed files with 813 additions and 926 deletions

View file

@ -36,6 +36,7 @@
#include "google_breakpad/processor/minidump.h"
#include "google_breakpad/processor/process_state.h"
#include "google_breakpad/processor/exploitability.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "processor/logging.h"
#include "processor/scoped_ptr.h"
#include "processor/stackwalker_x86.h"
@ -44,18 +45,29 @@ namespace google_breakpad {
MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: supplier_(supplier), resolver_(resolver),
: frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
own_frame_symbolizer_(true),
enable_exploitability_(false) {
}
MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier,
SourceLineResolverInterface *resolver,
bool enable_exploitability)
: supplier_(supplier), resolver_(resolver),
: frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)),
own_frame_symbolizer_(true),
enable_exploitability_(enable_exploitability) {
}
MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer,
bool enable_exploitability)
: frame_symbolizer_(frame_symbolizer),
own_frame_symbolizer_(false),
enable_exploitability_(enable_exploitability) {
assert(frame_symbolizer_);
}
MinidumpProcessor::~MinidumpProcessor() {
if (own_frame_symbolizer_) delete frame_symbolizer_;
}
ProcessResult MinidumpProcessor::Process(
@ -126,6 +138,10 @@ ProcessResult MinidumpProcessor::Process(
bool interrupted = false;
bool found_requesting_thread = false;
unsigned int thread_count = threads->thread_count();
// Reset frame_symbolizer_ at the beginning of stackwalk for each minidump.
frame_symbolizer_->Reset();
for (unsigned int thread_index = 0;
thread_index < thread_count;
++thread_index) {
@ -208,8 +224,7 @@ ProcessResult MinidumpProcessor::Process(
context,
thread_memory,
process_state->modules_,
supplier_,
resolver_));
frame_symbolizer_));
if (!stackwalker.get()) {
BPLOG(ERROR) << "No stackwalker for " << thread_string;
return PROCESS_ERROR_NO_STACKWALKER_FOR_THREAD;
@ -1160,7 +1175,8 @@ string MinidumpProcessor::GetAssertion(Minidump *dump) {
break;
default: {
char assertion_type[32];
sprintf(assertion_type, "0x%08x", raw_assertion->type);
snprintf(assertion_type, sizeof(assertion_type),
"0x%08x", raw_assertion->type);
assertion_string = "Unknown assertion type ";
assertion_string += assertion_type;
break;
@ -1184,7 +1200,7 @@ string MinidumpProcessor::GetAssertion(Minidump *dump) {
if (raw_assertion->line != 0) {
char assertion_line[32];
sprintf(assertion_line, "%u", raw_assertion->line);
snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line);
assertion_string.append(" at line ");
assertion_string.append(assertion_line);
}

View file

@ -41,9 +41,8 @@
#include "google_breakpad/processor/code_module.h"
#include "google_breakpad/processor/code_modules.h"
#include "google_breakpad/processor/minidump.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame.h"
#include "google_breakpad/processor/symbol_supplier.h"
#include "google_breakpad/processor/stack_frame_symbolizer.h"
#include "google_breakpad/processor/system_info.h"
#include "processor/linked_ptr.h"
#include "processor/logging.h"
@ -58,20 +57,19 @@ namespace google_breakpad {
u_int32_t Stackwalker::max_frames_ = 1024;
Stackwalker::Stackwalker(const SystemInfo *system_info,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
Stackwalker::Stackwalker(const SystemInfo* system_info,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer)
: system_info_(system_info),
memory_(memory),
modules_(modules),
resolver_(resolver),
supplier_(supplier) {
frame_symbolizer_(frame_symbolizer) {
assert(frame_symbolizer_);
}
bool Stackwalker::Walk(CallStack *stack) {
bool Stackwalker::Walk(CallStack* stack) {
BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|";
assert(stack);
stack->Clear();
@ -88,42 +86,12 @@ bool Stackwalker::Walk(CallStack *stack) {
// context frame (above) or a caller frame (below).
// Resolve the module information, if a module map was provided.
if (modules_) {
const CodeModule *module =
modules_->GetModuleForAddress(frame->instruction);
if (module) {
frame->module = module;
if (resolver_ &&
!resolver_->HasModule(frame->module) &&
no_symbol_modules_.find(
module->code_file()) == no_symbol_modules_.end() &&
supplier_) {
string symbol_file;
char *symbol_data = NULL;
SymbolSupplier::SymbolResult symbol_result =
supplier_->GetCStringSymbolData(module,
system_info_,
&symbol_file,
&symbol_data);
switch (symbol_result) {
case SymbolSupplier::FOUND:
resolver_->LoadModuleUsingMemoryBuffer(frame->module,
symbol_data);
break;
case SymbolSupplier::NOT_FOUND:
no_symbol_modules_.insert(module->code_file());
break; // nothing to do
case SymbolSupplier::INTERRUPT:
return false;
}
// Inform symbol supplier to free the unused data memory buffer.
if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule())
supplier_->FreeSymbolData(module);
}
if (resolver_)
resolver_->FillSourceLineInfo(frame.get());
}
StackFrameSymbolizer::SymbolizerResult symbolizer_result =
frame_symbolizer_->FillSourceLineInfo(modules_, system_info_,
frame.get());
if (symbolizer_result == StackFrameSymbolizer::INTERRUPT) {
BPLOG(INFO) << "Stack walk is interrupted.";
return false;
}
// Add the frame to the call stack. Relinquish the ownership claim
@ -144,47 +112,42 @@ bool Stackwalker::Walk(CallStack *stack) {
// static
Stackwalker* Stackwalker::StackwalkerForCPU(
const SystemInfo *system_info,
MinidumpContext *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver) {
const SystemInfo* system_info,
MinidumpContext* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer) {
if (!context) {
BPLOG(ERROR) << "Can't choose a stackwalker implementation without context";
return NULL;
}
Stackwalker *cpu_stackwalker = NULL;
Stackwalker* cpu_stackwalker = NULL;
u_int32_t cpu = context->GetContextCPU();
switch (cpu) {
case MD_CONTEXT_X86:
cpu_stackwalker = new StackwalkerX86(system_info,
context->GetContextX86(),
memory, modules, supplier,
resolver);
memory, modules, frame_symbolizer);
break;
case MD_CONTEXT_PPC:
cpu_stackwalker = new StackwalkerPPC(system_info,
context->GetContextPPC(),
memory, modules, supplier,
resolver);
memory, modules, frame_symbolizer);
break;
case MD_CONTEXT_AMD64:
cpu_stackwalker = new StackwalkerAMD64(system_info,
context->GetContextAMD64(),
memory, modules, supplier,
resolver);
memory, modules, frame_symbolizer);
break;
case MD_CONTEXT_SPARC:
cpu_stackwalker = new StackwalkerSPARC(system_info,
context->GetContextSPARC(),
memory, modules, supplier,
resolver);
memory, modules, frame_symbolizer);
break;
case MD_CONTEXT_ARM:
@ -193,8 +156,8 @@ Stackwalker* Stackwalker::StackwalkerForCPU(
fp_register = MD_CONTEXT_ARM_REG_IOS_FP;
cpu_stackwalker = new StackwalkerARM(system_info,
context->GetContextARM(),
fp_register, memory, modules,
supplier, resolver);
fp_register, memory, modules,
frame_symbolizer);
break;
}
@ -205,38 +168,28 @@ Stackwalker* Stackwalker::StackwalkerForCPU(
}
bool Stackwalker::InstructionAddressSeemsValid(u_int64_t address) {
const CodeModule *module = modules_->GetModuleForAddress(address);
if (!module) {
StackFrame frame;
frame.instruction = address;
StackFrameSymbolizer::SymbolizerResult symbolizer_result =
frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, &frame);
if (!frame.module) {
// not inside any loaded module
return false;
}
if (!resolver_ || !supplier_) {
// we don't have a resolver and or symbol supplier,
// but we're inside a known module
if (!frame_symbolizer_->HasImplementation()) {
// No valid implementation to symbolize stack frame, but the address is
// within a known module.
return true;
}
if (!resolver_->HasModule(module)) {
string symbol_file;
char *symbol_data = NULL;
SymbolSupplier::SymbolResult symbol_result =
supplier_->GetCStringSymbolData(module, system_info_,
&symbol_file, &symbol_data);
if (symbol_result != SymbolSupplier::FOUND ||
!resolver_->LoadModuleUsingMemoryBuffer(module,
symbol_data)) {
// we don't have symbols, but we're inside a loaded module
return true;
}
if (symbolizer_result != StackFrameSymbolizer::NO_ERROR) {
// Some error occurred during symbolization, but the address is within a
// known module
return true;
}
StackFrame frame;
frame.module = module;
frame.instruction = address;
resolver_->FillSourceLineInfo(&frame);
// we have symbols, so return true if inside a function
return !frame.function_name.empty();
}

View file

@ -89,13 +89,12 @@ StackwalkerAMD64::cfi_register_map_[] = {
StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip },
};
StackwalkerAMD64::StackwalkerAMD64(const SystemInfo *system_info,
const MDRawContextAMD64 *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: Stackwalker(system_info, memory, modules, supplier, resolver),
StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info,
const MDRawContextAMD64* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context),
cfi_walker_(cfi_register_map_,
(sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) {
@ -108,7 +107,7 @@ StackFrame* StackwalkerAMD64::GetContextFrame() {
return NULL;
}
StackFrameAMD64 *frame = new StackFrameAMD64();
StackFrameAMD64* frame = new StackFrameAMD64();
// The instruction pointer is stored directly in a register, so pull it
// straight out of the CPU context structure.
@ -120,10 +119,10 @@ StackFrame* StackwalkerAMD64::GetContextFrame() {
return frame;
}
StackFrameAMD64 *StackwalkerAMD64::GetCallerByCFIFrameInfo(
const vector<StackFrame *> &frames,
CFIFrameInfo *cfi_frame_info) {
StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64*>(frames.back());
StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo(
const vector<StackFrame*> &frames,
CFIFrameInfo* cfi_frame_info) {
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
scoped_ptr<StackFrameAMD64> frame(new StackFrameAMD64());
if (!cfi_walker_
@ -142,9 +141,9 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByCFIFrameInfo(
return frame.release();
}
StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan(
const vector<StackFrame *> &frames) {
StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64 *>(frames.back());
StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan(
const vector<StackFrame*> &frames) {
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
u_int64_t last_rsp = last_frame->context.rsp;
u_int64_t caller_rip_address, caller_rip;
@ -155,7 +154,7 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan(
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameAMD64 *frame = new StackFrameAMD64();
StackFrameAMD64* frame = new StackFrameAMD64();
frame->trust = StackFrame::FRAME_TRUST_SCAN;
frame->context = last_frame->context;
@ -191,19 +190,19 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByStackScan(
return frame;
}
StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack *stack) {
StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack) {
if (!memory_ || !stack) {
BPLOG(ERROR) << "Can't get caller frame without memory or stack";
return NULL;
}
const vector<StackFrame *> &frames = *stack->frames();
StackFrameAMD64 *last_frame = static_cast<StackFrameAMD64 *>(frames.back());
const vector<StackFrame*> &frames = *stack->frames();
StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back());
scoped_ptr<StackFrameAMD64> new_frame;
// If we have DWARF CFI information, use it.
scoped_ptr<CFIFrameInfo> cfi_frame_info(
resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL);
frame_symbolizer_->FindCFIFrameInfo(last_frame));
if (cfi_frame_info.get())
new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));

View file

@ -38,6 +38,7 @@
#ifndef PROCESSOR_STACKWALKER_AMD64_H__
#define PROCESSOR_STACKWALKER_AMD64_H__
#include <vector>
#include "google_breakpad/common/breakpad_types.h"
#include "google_breakpad/common/minidump_format.h"
@ -55,12 +56,11 @@ class StackwalkerAMD64 : public Stackwalker {
// 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.
StackwalkerAMD64(const SystemInfo *system_info,
const MDRawContextAMD64 *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
StackwalkerAMD64(const SystemInfo* system_info,
const MDRawContextAMD64* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
private:
// A STACK CFI-driven frame walker for the AMD64
@ -69,21 +69,21 @@ class StackwalkerAMD64 : public Stackwalker {
// Implementation of Stackwalker, using amd64 context (stack pointer in %rsp,
// stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp))
virtual StackFrame* GetContextFrame();
virtual StackFrame* GetCallerFrame(const CallStack *stack);
virtual StackFrame* GetCallerFrame(const CallStack* stack);
// Use cfi_frame_info (derived from STACK CFI records) to construct
// the frame that called frames.back(). The caller takes ownership
// of the returned frame. Return NULL on failure.
StackFrameAMD64 *GetCallerByCFIFrameInfo(const vector<StackFrame *> &frames,
CFIFrameInfo *cfi_frame_info);
StackFrameAMD64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
CFIFrameInfo* cfi_frame_info);
// Scan the stack for plausible return addresses. The caller takes ownership
// of the returned frame. Return NULL on failure.
StackFrameAMD64 *GetCallerByStackScan(const vector<StackFrame *> &frames);
// of the returned frame. Return NULL on failure.
StackFrameAMD64* GetCallerByStackScan(const vector<StackFrame*> &frames);
// Stores the CPU context corresponding to the innermost stack frame to
// be returned by GetContextFrame.
const MDRawContextAMD64 *context_;
const MDRawContextAMD64* context_;
// Our register map, for cfi_walker_.
static const CFIWalker::RegisterSet cfi_register_map_[];

View file

@ -31,8 +31,8 @@
// stackwalker_amd64_unittest.cc: Unit tests for StackwalkerAMD64 class.
#include <string>
#include <string.h>
#include <string>
#include <vector>
#include "breakpad_googletest_includes.h"
@ -48,6 +48,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameAMD64;
using google_breakpad::StackwalkerAMD64;
@ -112,7 +113,7 @@ class StackwalkerAMD64Fixture {
for (size_t i = 0; i < sizeof(*raw_context); i++)
reinterpret_cast<u_int8_t *>(raw_context)[i] = (x += 17);
}
SystemInfo system_info;
MDRawContextAMD64 raw_context;
Section stack_section;
@ -138,8 +139,9 @@ TEST_F(SanityCheck, NoResolver) {
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rbp = 0x8000000080000000ULL;
StackFrameSymbolizer frame_symbolizer(NULL, NULL);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
NULL, NULL);
&frame_symbolizer);
// This should succeed even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -158,8 +160,9 @@ TEST_F(GetContextFrame, Simple) {
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rbp = 0x8000000080000000ULL;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_GE(1U, frames->size());
@ -207,13 +210,14 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
.Append(32, 0); // end of stack
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rbp = frame1_rbp.Value();
raw_context.rsp = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -267,7 +271,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
.Append(32, 0) // end of stack
.Mark(&frame1_rbp);
RegionFromSection();
raw_context.rip = 0x40000000c0000200ULL;
raw_context.rbp = frame1_rbp.Value();
raw_context.rsp = stack_section.start().Value();
@ -279,8 +283,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
// The calling frame's function.
"FUNC 100 400 10 echidna\n");
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -343,8 +348,9 @@ TEST_F(GetCallerFrame, CallerPushedRBP) {
// The calling frame's function.
"FUNC 100 400 10 yeti\n");
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -418,8 +424,9 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
RegionFromSection();
raw_context.rsp = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());

View file

@ -33,6 +33,8 @@
//
// Author: Mark Mentovai, Ted Mielczarek, Jim Blandy
#include <vector>
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/memory_region.h"
#include "google_breakpad/processor/source_line_resolver_interface.h"
@ -45,14 +47,13 @@
namespace google_breakpad {
StackwalkerARM::StackwalkerARM(const SystemInfo *system_info,
const MDRawContextARM *context,
StackwalkerARM::StackwalkerARM(const SystemInfo* system_info,
const MDRawContextARM* context,
int fp_register,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: Stackwalker(system_info, memory, modules, supplier, resolver),
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context), fp_register_(fp_register),
context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { }
@ -63,7 +64,7 @@ StackFrame* StackwalkerARM::GetContextFrame() {
return NULL;
}
StackFrameARM *frame = new StackFrameARM();
StackFrameARM* frame = new StackFrameARM();
// The instruction pointer is stored directly in a register (r15), so pull it
// straight out of the CPU context structure.
@ -75,12 +76,12 @@ StackFrame* StackwalkerARM::GetContextFrame() {
return frame;
}
StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo(
const vector<StackFrame *> &frames,
CFIFrameInfo *cfi_frame_info) {
StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back());
StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo(
const vector<StackFrame*> &frames,
CFIFrameInfo* cfi_frame_info) {
StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
static const char *register_names[] = {
static const char* register_names[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc",
"f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
@ -121,7 +122,7 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo(
}
}
// If the CFI doesn't recover the PC explicitly, then use .ra.
if (! (frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) {
CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry =
caller_registers.find(".ra");
if (entry != caller_registers.end()) {
@ -140,7 +141,7 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo(
}
}
// If the CFI doesn't recover the SP explicitly, then use .cfa.
if (! (frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) {
CFIFrameInfo::RegisterValueMap<u_int32_t>::iterator entry =
caller_registers.find(".cfa");
if (entry != caller_registers.end()) {
@ -159,9 +160,9 @@ StackFrameARM *StackwalkerARM::GetCallerByCFIFrameInfo(
return frame.release();
}
StackFrameARM *StackwalkerARM::GetCallerByStackScan(
const vector<StackFrame *> &frames) {
StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back());
StackFrameARM* StackwalkerARM::GetCallerByStackScan(
const vector<StackFrame*> &frames) {
StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
u_int32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP];
u_int32_t caller_sp, caller_pc;
@ -177,7 +178,7 @@ StackFrameARM *StackwalkerARM::GetCallerByStackScan(
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameARM *frame = new StackFrameARM();
StackFrameARM* frame = new StackFrameARM();
frame->trust = StackFrame::FRAME_TRUST_SCAN;
frame->context = last_frame->context;
@ -189,9 +190,9 @@ StackFrameARM *StackwalkerARM::GetCallerByStackScan(
return frame;
}
StackFrameARM *StackwalkerARM::GetCallerByFramePointer(
const vector<StackFrame *> &frames) {
StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back());
StackFrameARM* StackwalkerARM::GetCallerByFramePointer(
const vector<StackFrame*> &frames) {
StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
if (!(last_frame->context_validity &
StackFrameARM::RegisterValidFlag(fp_register_))) {
@ -219,7 +220,7 @@ StackFrameARM *StackwalkerARM::GetCallerByFramePointer(
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameARM *frame = new StackFrameARM();
StackFrameARM* frame = new StackFrameARM();
frame->trust = StackFrame::FRAME_TRUST_FP;
frame->context = last_frame->context;
@ -235,19 +236,19 @@ StackFrameARM *StackwalkerARM::GetCallerByFramePointer(
return frame;
}
StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) {
StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack) {
if (!memory_ || !stack) {
BPLOG(ERROR) << "Can't get caller frame without memory or stack";
return NULL;
}
const vector<StackFrame *> &frames = *stack->frames();
StackFrameARM *last_frame = static_cast<StackFrameARM *>(frames.back());
const vector<StackFrame*> &frames = *stack->frames();
StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back());
scoped_ptr<StackFrameARM> frame;
// See if there is DWARF call frame information covering this address.
scoped_ptr<CFIFrameInfo> cfi_frame_info(
resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL);
frame_symbolizer_->FindCFIFrameInfo(last_frame));
if (cfi_frame_info.get())
frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));

View file

@ -54,13 +54,12 @@ class StackwalkerARM : public Stackwalker {
// 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,
StackwalkerARM(const SystemInfo* system_info,
const MDRawContextARM* context,
int fp_register,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
// Change the context validity mask of the frame returned by
// GetContextFrame to VALID. This is only for use by unit tests; the
@ -70,25 +69,25 @@ class StackwalkerARM : public Stackwalker {
private:
// Implementation of Stackwalker, using arm context and stack conventions.
virtual StackFrame* GetContextFrame();
virtual StackFrame* GetCallerFrame(const CallStack *stack);
virtual StackFrame* GetCallerFrame(const CallStack* stack);
// Use cfi_frame_info (derived from STACK CFI records) to construct
// the frame that called frames.back(). The caller takes ownership
// of the returned frame. Return NULL on failure.
StackFrameARM *GetCallerByCFIFrameInfo(const vector<StackFrame *> &frames,
CFIFrameInfo *cfi_frame_info);
StackFrameARM* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
CFIFrameInfo* cfi_frame_info);
// Use the frame pointer. The caller takes ownership of the returned frame.
// Return NULL on failure.
StackFrameARM *GetCallerByFramePointer(const vector<StackFrame *> &frames);
StackFrameARM* GetCallerByFramePointer(const vector<StackFrame*> &frames);
// Scan the stack for plausible return addresses. The caller takes ownership
// of the returned frame. Return NULL on failure.
StackFrameARM *GetCallerByStackScan(const vector<StackFrame *> &frames);
StackFrameARM* GetCallerByStackScan(const vector<StackFrame*> &frames);
// Stores the CPU context corresponding to the youngest stack frame, to
// be returned by GetContextFrame.
const MDRawContextARM *context_;
const MDRawContextARM* context_;
// The register to use a as frame pointer. The value is -1 if frame pointer
// cannot be used.

View file

@ -31,8 +31,8 @@
// stackwalker_arm_unittest.cc: Unit tests for StackwalkerARM class.
#include <string>
#include <string.h>
#include <string>
#include <vector>
#include "breakpad_googletest_includes.h"
@ -49,6 +49,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameARM;
using google_breakpad::StackwalkerARM;
@ -134,8 +135,9 @@ TEST_F(SanityCheck, NoResolver) {
// Since we have no call frame information, and all unwinding
// requires call frame information, the stack walk will end after
// the first frame.
StackFrameSymbolizer frame_symbolizer(NULL, NULL);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
NULL, NULL);
&frame_symbolizer);
// This should succeed even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -152,8 +154,9 @@ TEST_F(GetContextFrame, Simple) {
// Since we have no call frame information, and all unwinding
// requires call frame information, the stack walk will end after
// the first frame.
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
@ -199,8 +202,9 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510;
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -262,8 +266,9 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
// The calling frame's function.
"FUNC 100 400 10 marsupial\n");
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -372,8 +377,9 @@ struct CFIFixture: public StackwalkerARMFixture {
RegionFromSection();
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region,
&modules, &supplier, &resolver);
&modules, &frame_symbolizer);
walker.SetContextFrameValidity(context_frame_validity);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -564,8 +570,9 @@ TEST_F(CFI, RejectBackwards) {
raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40006000;
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000;
raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
@ -575,8 +582,9 @@ TEST_F(CFI, RejectBackwards) {
TEST_F(CFI, RejectBadExpressions) {
raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40007000;
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(1U, frames->size());
@ -631,8 +639,9 @@ TEST_F(GetFramesByFramePointer, OnlyFramePointer) {
raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value();
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
&stack_region, &modules, &supplier, &resolver);
&stack_region, &modules, &frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -720,8 +729,9 @@ TEST_F(GetFramesByFramePointer, FramePointerAndCFI) {
raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value();
raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP,
&stack_region, &modules, &supplier, &resolver);
&stack_region, &modules, &frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();

View file

@ -43,13 +43,12 @@
namespace google_breakpad {
StackwalkerPPC::StackwalkerPPC(const SystemInfo *system_info,
const MDRawContextPPC *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: Stackwalker(system_info, memory, modules, supplier, resolver),
StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info,
const MDRawContextPPC* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context) {
if (memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) {
// This implementation only covers 32-bit ppc CPUs. The limits of the
@ -69,7 +68,7 @@ StackFrame* StackwalkerPPC::GetContextFrame() {
return NULL;
}
StackFramePPC *frame = new StackFramePPC();
StackFramePPC* frame = new StackFramePPC();
// The instruction pointer is stored directly in a register, so pull it
// straight out of the CPU context structure.
@ -82,7 +81,7 @@ StackFrame* StackwalkerPPC::GetContextFrame() {
}
StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) {
StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack) {
if (!memory_ || !stack) {
BPLOG(ERROR) << "Can't get caller frame without memory or stack";
return NULL;
@ -97,7 +96,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) {
// frame pointer, and what is typically thought of as the frame pointer on
// an x86 is usually referred to as the stack pointer on a ppc.
StackFramePPC *last_frame = static_cast<StackFramePPC*>(
StackFramePPC* last_frame = static_cast<StackFramePPC*>(
stack->frames()->back());
// A caller frame must reside higher in memory than its callee frames.
@ -121,7 +120,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) {
return NULL;
}
StackFramePPC *frame = new StackFramePPC();
StackFramePPC* frame = new StackFramePPC();
frame->context = last_frame->context;
frame->context.srr0 = instruction;

View file

@ -53,23 +53,22 @@ class StackwalkerPPC : public Stackwalker {
// 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.
StackwalkerPPC(const SystemInfo *system_info,
const MDRawContextPPC *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
StackwalkerPPC(const SystemInfo* system_info,
const MDRawContextPPC* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
private:
// Implementation of Stackwalker, using ppc context (stack pointer in %r1,
// saved program counter in %srr0) and stack conventions (saved stack
// pointer at 0(%r1), return address at 8(0(%r1)).
virtual StackFrame* GetContextFrame();
virtual StackFrame* GetCallerFrame(const CallStack *stack);
virtual StackFrame* GetCallerFrame(const CallStack* stack);
// Stores the CPU context corresponding to the innermost stack frame to
// be returned by GetContextFrame.
const MDRawContextPPC *context_;
const MDRawContextPPC* context_;
};

View file

@ -43,13 +43,12 @@
namespace google_breakpad {
StackwalkerSPARC::StackwalkerSPARC(const SystemInfo *system_info,
const MDRawContextSPARC *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: Stackwalker(system_info, memory, modules, supplier, resolver),
StackwalkerSPARC::StackwalkerSPARC(const SystemInfo* system_info,
const MDRawContextSPARC* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context) {
}
@ -60,7 +59,7 @@ StackFrame* StackwalkerSPARC::GetContextFrame() {
return NULL;
}
StackFrameSPARC *frame = new StackFrameSPARC();
StackFrameSPARC* frame = new StackFrameSPARC();
// The instruction pointer is stored directly in a register, so pull it
// straight out of the CPU context structure.
@ -73,13 +72,13 @@ StackFrame* StackwalkerSPARC::GetContextFrame() {
}
StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) {
StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack) {
if (!memory_ || !stack) {
BPLOG(ERROR) << "Can't get caller frame without memory or stack";
return NULL;
}
StackFrameSPARC *last_frame = static_cast<StackFrameSPARC*>(
StackFrameSPARC* last_frame = static_cast<StackFrameSPARC*>(
stack->frames()->back());
// new: caller
@ -87,7 +86,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) {
// %fp, %i6 and g_r[30] is the same, see minidump_format.h
// %sp, %o6 and g_r[14] is the same, see minidump_format.h
// %sp_new = %fp_old
// %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6
// %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6
// %pc_new = *(%fp_old + 32 + 32 - 4) + 8
// which is callee's %i7 plus 8
@ -111,14 +110,14 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) {
return NULL;
}
StackFrameSPARC *frame = new StackFrameSPARC();
StackFrameSPARC* frame = new StackFrameSPARC();
frame->context = last_frame->context;
frame->context.g_r[14] = stack_pointer;
frame->context.g_r[30] = stack_base;
// frame->context.pc is the return address, which is 2 instruction
// past the branch that caused us to arrive at the callee, which are
// past the branch that caused us to arrive at the callee, which are
// a CALL instruction then a NOP instruction.
// frame_ppc->instruction to 8 less than that. Since all sparc
// instructions are 4 bytes wide, this is the address of the branch
@ -131,7 +130,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) {
StackFrameSPARC::CONTEXT_VALID_SP |
StackFrameSPARC::CONTEXT_VALID_FP;
frame->trust = StackFrame::FRAME_TRUST_FP;
return frame;
}

View file

@ -53,22 +53,21 @@ class StackwalkerSPARC : public Stackwalker {
// 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.
StackwalkerSPARC(const SystemInfo *system_info,
const MDRawContextSPARC *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
StackwalkerSPARC(const SystemInfo* system_info,
const MDRawContextSPARC* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
private:
// Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and
// stack conventions
virtual StackFrame* GetContextFrame();
virtual StackFrame* GetCallerFrame(const CallStack *stack);
virtual StackFrame* GetCallerFrame(const CallStack* stack);
// Stores the CPU context corresponding to the innermost stack frame to
// be returned by GetContextFrame.
const MDRawContextSPARC *context_;
const MDRawContextSPARC* context_;
};

View file

@ -33,8 +33,7 @@
//
// Author: Mark Mentovai
#include "processor/postfix_evaluator-inl.h"
#include <string>
#include "google_breakpad/processor/call_stack.h"
#include "google_breakpad/processor/code_modules.h"
@ -42,6 +41,7 @@
#include "google_breakpad/processor/source_line_resolver_interface.h"
#include "google_breakpad/processor/stack_frame_cpu.h"
#include "processor/logging.h"
#include "processor/postfix_evaluator-inl.h"
#include "processor/scoped_ptr.h"
#include "processor/stackwalker_x86.h"
#include "processor/windows_frame_info.h"
@ -77,13 +77,12 @@ StackwalkerX86::cfi_register_map_[] = {
StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi },
};
StackwalkerX86::StackwalkerX86(const SystemInfo *system_info,
const MDRawContextX86 *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver)
: Stackwalker(system_info, memory, modules, supplier, resolver),
StackwalkerX86::StackwalkerX86(const SystemInfo* system_info,
const MDRawContextX86* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* resolver_helper)
: Stackwalker(system_info, memory, modules, resolver_helper),
context_(context),
cfi_walker_(cfi_register_map_,
(sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) {
@ -106,13 +105,13 @@ StackFrameX86::~StackFrameX86() {
cfi_frame_info = NULL;
}
StackFrame *StackwalkerX86::GetContextFrame() {
StackFrame* StackwalkerX86::GetContextFrame() {
if (!context_ || !memory_) {
BPLOG(ERROR) << "Can't get context frame without context or memory";
return NULL;
}
StackFrameX86 *frame = new StackFrameX86();
StackFrameX86* frame = new StackFrameX86();
// The instruction pointer is stored directly in a register, so pull it
// straight out of the CPU context structure.
@ -124,12 +123,12 @@ StackFrame *StackwalkerX86::GetContextFrame() {
return frame;
}
StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
const vector<StackFrame *> &frames,
WindowsFrameInfo *last_frame_info) {
StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo(
const vector<StackFrame*> &frames,
WindowsFrameInfo* last_frame_info) {
StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE;
StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back());
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
// Save the stack walking info we found, in case we need it later to
// find the callee of the frame we're constructing now.
@ -176,9 +175,9 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
u_int32_t last_frame_callee_parameter_size = 0;
int frames_already_walked = frames.size();
if (frames_already_walked >= 2) {
const StackFrameX86 *last_frame_callee
= static_cast<StackFrameX86 *>(frames[frames_already_walked - 2]);
WindowsFrameInfo *last_frame_callee_info
const StackFrameX86* last_frame_callee
= static_cast<StackFrameX86*>(frames[frames_already_walked - 2]);
WindowsFrameInfo* last_frame_callee_info
= last_frame_callee->windows_frame_info;
if (last_frame_callee_info &&
(last_frame_callee_info->valid
@ -210,7 +209,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
last_frame_info->saved_register_size;
u_int32_t raSearchStartOld = raSearchStart;
u_int32_t found = 0; // dummy value
u_int32_t found = 0; // dummy value
// Scan up to three words above the calculated search value, in case
// the stack was aligned to a quadword boundary.
if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) &&
@ -419,7 +418,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameX86 *frame = new StackFrameX86();
StackFrameX86* frame = new StackFrameX86();
frame->trust = trust;
frame->context = last_frame->context;
@ -448,10 +447,10 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
return frame;
}
StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo(
StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo(
const vector<StackFrame*> &frames,
CFIFrameInfo *cfi_frame_info) {
StackFrameX86 *last_frame = static_cast<StackFrameX86*>(frames.back());
CFIFrameInfo* cfi_frame_info) {
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
last_frame->cfi_frame_info = cfi_frame_info;
scoped_ptr<StackFrameX86> frame(new StackFrameX86());
@ -460,7 +459,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo(
last_frame->context, last_frame->context_validity,
&frame->context, &frame->context_validity))
return NULL;
// Make sure we recovered all the essentials.
static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP
| StackFrameX86::CONTEXT_VALID_ESP
@ -473,10 +472,10 @@ StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo(
return frame.release();
}
StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
const vector<StackFrame *> &frames) {
StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase(
const vector<StackFrame*> &frames) {
StackFrame::FrameTrust trust;
StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back());
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
u_int32_t last_esp = last_frame->context.esp;
u_int32_t last_ebp = last_frame->context.ebp;
@ -532,7 +531,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
// Create a new stack frame (ownership will be transferred to the caller)
// and fill it in.
StackFrameX86 *frame = new StackFrameX86();
StackFrameX86* frame = new StackFrameX86();
frame->trust = trust;
frame->context = last_frame->context;
@ -546,26 +545,26 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
return frame;
}
StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) {
StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack) {
if (!memory_ || !stack) {
BPLOG(ERROR) << "Can't get caller frame without memory or stack";
return NULL;
}
const vector<StackFrame *> &frames = *stack->frames();
StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back());
const vector<StackFrame*> &frames = *stack->frames();
StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back());
scoped_ptr<StackFrameX86> new_frame;
// If the resolver has Windows stack walking information, use that.
WindowsFrameInfo *windows_frame_info
= resolver_ ? resolver_->FindWindowsFrameInfo(last_frame) : NULL;
WindowsFrameInfo* windows_frame_info
= frame_symbolizer_->FindWindowsFrameInfo(last_frame);
if (windows_frame_info)
new_frame.reset(GetCallerByWindowsFrameInfo(frames, windows_frame_info));
// If the resolver has DWARF CFI information, use that.
if (!new_frame.get()) {
CFIFrameInfo *cfi_frame_info =
resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL;
CFIFrameInfo* cfi_frame_info =
frame_symbolizer_->FindCFIFrameInfo(last_frame);
if (cfi_frame_info)
new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info));
}
@ -577,7 +576,7 @@ StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) {
// If nothing worked, tell the caller.
if (!new_frame.get())
return NULL;
// Treat an instruction address of 0 as end-of-stack.
if (new_frame->context.eip == 0)
return NULL;

View file

@ -1,4 +1,4 @@
// -*- mode: c++ -*-
// -*- mode: c++ -*-
// Copyright (c) 2010 Google Inc.
// All rights reserved.
@ -40,6 +40,7 @@
#ifndef PROCESSOR_STACKWALKER_X86_H__
#define PROCESSOR_STACKWALKER_X86_H__
#include <vector>
#include "google_breakpad/common/breakpad_types.h"
#include "google_breakpad/common/minidump_format.h"
@ -58,12 +59,11 @@ class StackwalkerX86 : public Stackwalker {
// 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.
StackwalkerX86(const SystemInfo *system_info,
const MDRawContextX86 *context,
MemoryRegion *memory,
const CodeModules *modules,
SymbolSupplier *supplier,
SourceLineResolverInterface *resolver);
StackwalkerX86(const SystemInfo* system_info,
const MDRawContextX86* context,
MemoryRegion* memory,
const CodeModules* modules,
StackFrameSymbolizer* frame_symbolizer);
private:
// A STACK CFI-driven frame walker for the X86.
@ -73,32 +73,32 @@ class StackwalkerX86 : public Stackwalker {
// stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or
// alternate conventions as guided by any WindowsFrameInfo available for the
// code in question.).
virtual StackFrame *GetContextFrame();
virtual StackFrame *GetCallerFrame(const CallStack *stack);
virtual StackFrame* GetContextFrame();
virtual StackFrame* GetCallerFrame(const CallStack* stack);
// Use windows_frame_info (derived from STACK WIN and FUNC records)
// to construct the frame that called frames.back(). The caller
// takes ownership of the returned frame. Return NULL on failure.
StackFrameX86 *GetCallerByWindowsFrameInfo(
StackFrameX86* GetCallerByWindowsFrameInfo(
const vector<StackFrame*> &frames,
WindowsFrameInfo *windows_frame_info);
WindowsFrameInfo* windows_frame_info);
// Use cfi_frame_info (derived from STACK CFI records) to construct
// the frame that called frames.back(). The caller takes ownership
// of the returned frame. Return NULL on failure.
StackFrameX86 *GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
CFIFrameInfo *cfi_frame_info);
StackFrameX86* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames,
CFIFrameInfo* cfi_frame_info);
// Assuming a traditional frame layout --- where the caller's %ebp
// has been pushed just after the return address and the callee's
// %ebp points to the saved %ebp --- construct the frame that called
// frames.back(). The caller takes ownership of the returned frame.
// Return NULL on failure.
StackFrameX86 *GetCallerByEBPAtBase(const vector<StackFrame*> &frames);
StackFrameX86* GetCallerByEBPAtBase(const vector<StackFrame*> &frames);
// Stores the CPU context corresponding to the innermost stack frame to
// be returned by GetContextFrame.
const MDRawContextX86 *context_;
const MDRawContextX86* context_;
// Our register map, for cfi_walker_.
static const CFIWalker::RegisterSet cfi_register_map_[];

View file

@ -48,6 +48,7 @@
using google_breakpad::BasicSourceLineResolver;
using google_breakpad::CallStack;
using google_breakpad::StackFrameSymbolizer;
using google_breakpad::StackFrame;
using google_breakpad::StackFrameX86;
using google_breakpad::StackwalkerX86;
@ -148,8 +149,9 @@ TEST_F(SanityCheck, NoResolver) {
raw_context.eip = 0x40000200;
raw_context.ebp = 0x80000000;
StackFrameSymbolizer frame_symbolizer(NULL, NULL);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
NULL, NULL);
&frame_symbolizer);
// This should succeed, even without a resolver or supplier.
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -168,8 +170,9 @@ TEST_F(GetContextFrame, Simple) {
raw_context.eip = 0x40000200;
raw_context.ebp = 0x80000000;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
@ -200,8 +203,9 @@ TEST_F(GetCallerFrame, Traditional) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = frame0_ebp.Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -255,8 +259,9 @@ TEST_F(GetCallerFrame, TraditionalScan) {
// for something that looks like a return address.
raw_context.ebp = 0xd43eed6e;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -316,8 +321,9 @@ TEST_F(GetCallerFrame, TraditionalScanLongWay) {
// for something that looks like a return address.
raw_context.ebp = 0xd43eed6e;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -387,8 +393,9 @@ TEST_F(GetCallerFrame, WindowsFrameData) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -458,8 +465,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataAligned) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = 0xf052c1de; // should not be needed to walk frame
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -540,8 +548,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = frame0_ebp.Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(3U, frames->size());
@ -634,8 +643,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -717,8 +727,9 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
raw_context.esp = stack_section.start().Value();
raw_context.ebp = frame0_ebp.Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -784,8 +795,9 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
// Frame pointer unchanged from caller.
raw_context.ebp = frame1_ebp.Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -860,8 +872,9 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
// RaisedByTheAliens uses %ebp for its own mysterious purposes.
raw_context.ebp = 0xecbdd1a5;
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());
@ -997,8 +1010,9 @@ TEST_F(GetCallerFrame, WindowsFPOSystemCall) {
ASSERT_TRUE(raw_context.esp == frame0_esp.Value());
raw_context.ebp = frame1_ebp.Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
@ -1097,8 +1111,9 @@ struct CFIFixture: public StackwalkerX86Fixture {
RegionFromSection();
raw_context.esp = stack_section.start().Value();
StackFrameSymbolizer frame_symbolizer(&supplier, &resolver);
StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
&supplier, &resolver);
&frame_symbolizer);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_EQ(2U, frames->size());