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
This commit is contained in:
parent
de2c055770
commit
8c33b3e9c9
@ -40,6 +40,19 @@ class CodeModule;
|
|||||||
using std::string;
|
using std::string;
|
||||||
|
|
||||||
struct StackFrame {
|
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()
|
StackFrame()
|
||||||
: instruction(),
|
: instruction(),
|
||||||
module(NULL),
|
module(NULL),
|
||||||
@ -47,9 +60,29 @@ struct StackFrame {
|
|||||||
function_base(),
|
function_base(),
|
||||||
source_file_name(),
|
source_file_name(),
|
||||||
source_line(),
|
source_line(),
|
||||||
source_line_base() {}
|
source_line_base(),
|
||||||
|
trust(FRAME_TRUST_NONE) {}
|
||||||
virtual ~StackFrame() {}
|
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
|
// The program counter location as an absolute virtual address. For the
|
||||||
// innermost called frame in a stack, this will be an exact program counter
|
// 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
|
// 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
|
// The start address of the source line, may be omitted if debug symbols
|
||||||
// are not available.
|
// are not available.
|
||||||
u_int64_t source_line_base;
|
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
|
} // namespace google_breakpad
|
||||||
|
@ -70,23 +70,9 @@ struct StackFrameX86 : public StackFrame {
|
|||||||
CONTEXT_VALID_ALL = -1
|
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()
|
StackFrameX86()
|
||||||
: context(),
|
: context(),
|
||||||
context_validity(CONTEXT_VALID_NONE),
|
context_validity(CONTEXT_VALID_NONE),
|
||||||
trust(FRAME_TRUST_NONE),
|
|
||||||
windows_frame_info(NULL),
|
windows_frame_info(NULL),
|
||||||
cfi_frame_info(NULL) {}
|
cfi_frame_info(NULL) {}
|
||||||
~StackFrameX86();
|
~StackFrameX86();
|
||||||
@ -101,10 +87,6 @@ struct StackFrameX86 : public StackFrame {
|
|||||||
// the OR operator doesn't work well with enumerated types. This indicates
|
// the OR operator doesn't work well with enumerated types. This indicates
|
||||||
// which fields in context are valid.
|
// which fields in context are valid.
|
||||||
int context_validity;
|
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.
|
// Any stack walking information we found describing this.instruction.
|
||||||
// These may be NULL if there is no such information for that address.
|
// These may be NULL if there is no such information for that address.
|
||||||
|
@ -44,12 +44,12 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "google_breakpad/common/breakpad_types.h"
|
#include "google_breakpad/common/breakpad_types.h"
|
||||||
|
#include "google_breakpad/processor/code_modules.h"
|
||||||
|
#include "google_breakpad/processor/memory_region.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
class CallStack;
|
class CallStack;
|
||||||
class CodeModules;
|
|
||||||
class MemoryRegion;
|
|
||||||
class MinidumpContext;
|
class MinidumpContext;
|
||||||
class SourceLineResolverInterface;
|
class SourceLineResolverInterface;
|
||||||
struct StackFrame;
|
struct StackFrame;
|
||||||
@ -108,6 +108,39 @@ class Stackwalker {
|
|||||||
// Returns false otherwise.
|
// Returns false otherwise.
|
||||||
bool InstructionAddressSeemsValid(u_int64_t address);
|
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<typename InstructionType>
|
||||||
|
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
|
// Information about the system that produced the minidump. Subclasses
|
||||||
// and the SymbolSupplier may find this information useful.
|
// and the SymbolSupplier may find this information useful.
|
||||||
const SystemInfo *system_info_;
|
const SystemInfo *system_info_;
|
||||||
|
@ -146,7 +146,7 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
|
|||||||
int sequence = 0;
|
int sequence = 0;
|
||||||
if (cpu == "x86") {
|
if (cpu == "x86") {
|
||||||
const StackFrameX86 *frame_x86 =
|
const StackFrameX86 *frame_x86 =
|
||||||
reinterpret_cast<const StackFrameX86*>(frame);
|
reinterpret_cast<const StackFrameX86*>(frame);
|
||||||
|
|
||||||
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
|
if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP)
|
||||||
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
|
sequence = PrintRegister("eip", frame_x86->context.eip, sequence);
|
||||||
@ -166,32 +166,9 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
|
|||||||
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
|
sequence = PrintRegister("edx", frame_x86->context.edx, sequence);
|
||||||
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
|
sequence = PrintRegister("efl", frame_x86->context.eflags, sequence);
|
||||||
}
|
}
|
||||||
const char *trust_name;
|
|
||||||
switch (frame_x86->trust) {
|
|
||||||
default:
|
|
||||||
case StackFrameX86::FRAME_TRUST_NONE:
|
|
||||||
trust_name = "unknown";
|
|
||||||
break;
|
|
||||||
case StackFrameX86::FRAME_TRUST_CONTEXT:
|
|
||||||
trust_name = "given as instruction pointer in context";
|
|
||||||
break;
|
|
||||||
case StackFrameX86::FRAME_TRUST_CFI:
|
|
||||||
trust_name = "call frame info";
|
|
||||||
break;
|
|
||||||
case StackFrameX86::FRAME_TRUST_CFI_SCAN:
|
|
||||||
trust_name = "call frame info with scanning";
|
|
||||||
break;
|
|
||||||
case StackFrameX86::FRAME_TRUST_FP:
|
|
||||||
trust_name = "previous frame's frame pointer";
|
|
||||||
break;
|
|
||||||
case StackFrameX86::FRAME_TRUST_SCAN:
|
|
||||||
trust_name = "stack scanning";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("\n Found by: %s", trust_name);
|
|
||||||
} else if (cpu == "ppc") {
|
} else if (cpu == "ppc") {
|
||||||
const StackFramePPC *frame_ppc =
|
const StackFramePPC *frame_ppc =
|
||||||
reinterpret_cast<const StackFramePPC*>(frame);
|
reinterpret_cast<const StackFramePPC*>(frame);
|
||||||
|
|
||||||
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
|
if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0)
|
||||||
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
|
sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence);
|
||||||
@ -219,7 +196,7 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
|
|||||||
sequence = PrintRegister("rbp", frame_amd64->context.rbp, sequence);
|
sequence = PrintRegister("rbp", frame_amd64->context.rbp, sequence);
|
||||||
} else if (cpu == "sparc") {
|
} else if (cpu == "sparc") {
|
||||||
const StackFrameSPARC *frame_sparc =
|
const StackFrameSPARC *frame_sparc =
|
||||||
reinterpret_cast<const StackFrameSPARC*>(frame);
|
reinterpret_cast<const StackFrameSPARC*>(frame);
|
||||||
|
|
||||||
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
|
if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP)
|
||||||
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
|
sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence);
|
||||||
@ -229,7 +206,7 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
|
|||||||
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
|
sequence = PrintRegister("pc", frame_sparc->context.pc, sequence);
|
||||||
} else if (cpu == "arm") {
|
} else if (cpu == "arm") {
|
||||||
const StackFrameARM *frame_arm =
|
const StackFrameARM *frame_arm =
|
||||||
reinterpret_cast<const StackFrameARM*>(frame);
|
reinterpret_cast<const StackFrameARM*>(frame);
|
||||||
|
|
||||||
// General-purpose callee-saves registers.
|
// General-purpose callee-saves registers.
|
||||||
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
|
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4)
|
||||||
@ -257,7 +234,7 @@ static void PrintStack(const CallStack *stack, const string &cpu) {
|
|||||||
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
|
if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC)
|
||||||
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
|
sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n Found by: %s\n", frame->trust_description().c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,6 +114,7 @@ StackFrame* StackwalkerAMD64::GetContextFrame() {
|
|||||||
// straight out of the CPU context structure.
|
// straight out of the CPU context structure.
|
||||||
frame->context = *context_;
|
frame->context = *context_;
|
||||||
frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL;
|
frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
|
||||||
frame->instruction = frame->context.rip;
|
frame->instruction = frame->context.rip;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
@ -137,6 +138,7 @@ StackFrameAMD64 *StackwalkerAMD64::GetCallerByCFIFrameInfo(
|
|||||||
if ((frame->context_validity & essentials) != essentials)
|
if ((frame->context_validity & essentials) != essentials)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CFI;
|
||||||
return frame.release();
|
return frame.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,11 +202,13 @@ struct CFIFixture: public StackwalkerAMD64Fixture {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
|
StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0));
|
||||||
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ("enchiridion", frame0->function_name);
|
EXPECT_EQ("enchiridion", frame0->function_name);
|
||||||
EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
|
EXPECT_EQ(0x40000000c0004000ULL, frame0->function_base);
|
||||||
|
|
||||||
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
|
||||||
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
|
ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP |
|
||||||
StackFrameAMD64::CONTEXT_VALID_RSP |
|
StackFrameAMD64::CONTEXT_VALID_RSP |
|
||||||
StackFrameAMD64::CONTEXT_VALID_RBP |
|
StackFrameAMD64::CONTEXT_VALID_RBP |
|
||||||
|
@ -69,6 +69,7 @@ StackFrame* StackwalkerARM::GetContextFrame() {
|
|||||||
// straight out of the CPU context structure.
|
// straight out of the CPU context structure.
|
||||||
frame->context = *context_;
|
frame->context = *context_;
|
||||||
frame->context_validity = context_frame_validity_;
|
frame->context_validity = context_frame_validity_;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
|
||||||
frame->instruction = frame->context.iregs[15];
|
frame->instruction = frame->context.iregs[15];
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
@ -178,6 +179,7 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) {
|
|||||||
// frame->context.iregs[MD_CONTEXT_ARM_REG_PC].
|
// frame->context.iregs[MD_CONTEXT_ARM_REG_PC].
|
||||||
frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 1;
|
frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 1;
|
||||||
|
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CFI;
|
||||||
return frame.release();
|
return frame.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -238,11 +238,13 @@ struct CFIFixture: public StackwalkerARMFixture {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
|
StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
|
||||||
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(context_frame_validity, frame0->context_validity);
|
ASSERT_EQ(context_frame_validity, frame0->context_validity);
|
||||||
EXPECT_EQ("enchiridion", frame0->function_name);
|
EXPECT_EQ("enchiridion", frame0->function_name);
|
||||||
EXPECT_EQ(0x40004000U, frame0->function_base);
|
EXPECT_EQ(0x40004000U, frame0->function_base);
|
||||||
|
|
||||||
StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
|
StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
|
||||||
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ(expected_validity, frame1->context_validity);
|
ASSERT_EQ(expected_validity, frame1->context_validity);
|
||||||
if (expected_validity & StackFrameARM::CONTEXT_VALID_R1)
|
if (expected_validity & StackFrameARM::CONTEXT_VALID_R1)
|
||||||
EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
|
EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]);
|
||||||
|
@ -75,6 +75,7 @@ StackFrame* StackwalkerPPC::GetContextFrame() {
|
|||||||
// straight out of the CPU context structure.
|
// straight out of the CPU context structure.
|
||||||
frame->context = *context_;
|
frame->context = *context_;
|
||||||
frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL;
|
frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
|
||||||
frame->instruction = frame->context.srr0;
|
frame->instruction = frame->context.srr0;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
@ -127,6 +128,7 @@ StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack *stack) {
|
|||||||
frame->context.gpr[1] = stack_pointer;
|
frame->context.gpr[1] = stack_pointer;
|
||||||
frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 |
|
frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 |
|
||||||
StackFramePPC::CONTEXT_VALID_GPR1;
|
StackFramePPC::CONTEXT_VALID_GPR1;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_FP;
|
||||||
|
|
||||||
// frame->context.srr0 is the return address, which is one instruction
|
// frame->context.srr0 is the return address, which is one instruction
|
||||||
// past the branch that caused us to arrive at the callee. Set
|
// past the branch that caused us to arrive at the callee. Set
|
||||||
|
@ -66,6 +66,7 @@ StackFrame* StackwalkerSPARC::GetContextFrame() {
|
|||||||
// straight out of the CPU context structure.
|
// straight out of the CPU context structure.
|
||||||
frame->context = *context_;
|
frame->context = *context_;
|
||||||
frame->context_validity = StackFrameSPARC::CONTEXT_VALID_ALL;
|
frame->context_validity = StackFrameSPARC::CONTEXT_VALID_ALL;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
|
||||||
frame->instruction = frame->context.pc;
|
frame->instruction = frame->context.pc;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
@ -129,6 +130,7 @@ StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack *stack) {
|
|||||||
frame->context_validity = StackFrameSPARC::CONTEXT_VALID_PC |
|
frame->context_validity = StackFrameSPARC::CONTEXT_VALID_PC |
|
||||||
StackFrameSPARC::CONTEXT_VALID_SP |
|
StackFrameSPARC::CONTEXT_VALID_SP |
|
||||||
StackFrameSPARC::CONTEXT_VALID_FP;
|
StackFrameSPARC::CONTEXT_VALID_FP;
|
||||||
|
frame->trust = StackFrame::FRAME_TRUST_FP;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ StackFrame *StackwalkerX86::GetContextFrame() {
|
|||||||
// straight out of the CPU context structure.
|
// straight out of the CPU context structure.
|
||||||
frame->context = *context_;
|
frame->context = *context_;
|
||||||
frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL;
|
frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL;
|
||||||
frame->trust = StackFrameX86::FRAME_TRUST_CONTEXT;
|
frame->trust = StackFrame::FRAME_TRUST_CONTEXT;
|
||||||
frame->instruction = frame->context.eip;
|
frame->instruction = frame->context.eip;
|
||||||
|
|
||||||
return frame;
|
return frame;
|
||||||
@ -127,7 +127,7 @@ StackFrame *StackwalkerX86::GetContextFrame() {
|
|||||||
StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
|
StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
|
||||||
const vector<StackFrame *> &frames,
|
const vector<StackFrame *> &frames,
|
||||||
WindowsFrameInfo *last_frame_info) {
|
WindowsFrameInfo *last_frame_info) {
|
||||||
StackFrameX86::FrameTrust trust = StackFrameX86::FRAME_TRUST_NONE;
|
StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE;
|
||||||
|
|
||||||
StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back());
|
StackFrameX86 *last_frame = static_cast<StackFrameX86 *>(frames.back());
|
||||||
|
|
||||||
@ -219,7 +219,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||||||
string program_string;
|
string program_string;
|
||||||
bool recover_ebp = true;
|
bool recover_ebp = true;
|
||||||
|
|
||||||
trust = StackFrameX86::FRAME_TRUST_CFI;
|
trust = StackFrame::FRAME_TRUST_CFI;
|
||||||
if (!last_frame_info->program_string.empty()) {
|
if (!last_frame_info->program_string.empty()) {
|
||||||
// The FPO data has its own program string, which will tell us how to
|
// The FPO data has its own program string, which will tell us how to
|
||||||
// get to the caller frame, and may even fill in the values of
|
// get to the caller frame, and may even fill in the values of
|
||||||
@ -318,7 +318,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||||||
// one where the return address was found.
|
// one where the return address was found.
|
||||||
dictionary["$eip"] = eip;
|
dictionary["$eip"] = eip;
|
||||||
dictionary["$esp"] = location + 4;
|
dictionary["$esp"] = location + 4;
|
||||||
trust = StackFrameX86::FRAME_TRUST_SCAN;
|
trust = StackFrame::FRAME_TRUST_SCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since this stack frame did not use %ebp in a traditional way,
|
// Since this stack frame did not use %ebp in a traditional way,
|
||||||
@ -356,7 +356,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByWindowsFrameInfo(
|
|||||||
dictionary["$eip"] = eip;
|
dictionary["$eip"] = eip;
|
||||||
dictionary["$esp"] = location + 4;
|
dictionary["$esp"] = location + 4;
|
||||||
offset = location - location_start;
|
offset = location - location_start;
|
||||||
trust = StackFrameX86::FRAME_TRUST_CFI_SCAN;
|
trust = StackFrame::FRAME_TRUST_CFI_SCAN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,14 +441,14 @@ StackFrameX86 *StackwalkerX86::GetCallerByCFIFrameInfo(
|
|||||||
if ((frame->context_validity & essentials) != essentials)
|
if ((frame->context_validity & essentials) != essentials)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
frame->trust = StackFrameX86::FRAME_TRUST_CFI;
|
frame->trust = StackFrame::FRAME_TRUST_CFI;
|
||||||
|
|
||||||
return frame.release();
|
return frame.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
|
StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
|
||||||
const vector<StackFrame *> &frames) {
|
const vector<StackFrame *> &frames) {
|
||||||
StackFrameX86::FrameTrust trust;
|
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_esp = last_frame->context.esp;
|
||||||
u_int32_t last_ebp = last_frame->context.ebp;
|
u_int32_t last_ebp = last_frame->context.ebp;
|
||||||
@ -481,7 +481,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
|
|||||||
if (memory_->GetMemoryAtAddress(last_ebp + 4, &caller_eip) &&
|
if (memory_->GetMemoryAtAddress(last_ebp + 4, &caller_eip) &&
|
||||||
memory_->GetMemoryAtAddress(last_ebp, &caller_ebp)) {
|
memory_->GetMemoryAtAddress(last_ebp, &caller_ebp)) {
|
||||||
caller_esp = last_ebp + 8;
|
caller_esp = last_ebp + 8;
|
||||||
trust = StackFrameX86::FRAME_TRUST_FP;
|
trust = StackFrame::FRAME_TRUST_FP;
|
||||||
} else {
|
} else {
|
||||||
// We couldn't read the memory %ebp refers to. It may be that %ebp
|
// We couldn't read the memory %ebp refers to. It may be that %ebp
|
||||||
// is pointing to non-stack memory. We'll scan the stack for a
|
// is pointing to non-stack memory. We'll scan the stack for a
|
||||||
@ -500,7 +500,7 @@ StackFrameX86 *StackwalkerX86::GetCallerByEBPAtBase(
|
|||||||
caller_esp += 4;
|
caller_esp += 4;
|
||||||
caller_ebp = last_ebp;
|
caller_ebp = last_ebp;
|
||||||
|
|
||||||
trust = StackFrameX86::FRAME_TRUST_SCAN;
|
trust = StackFrame::FRAME_TRUST_SCAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new stack frame (ownership will be transferred to the caller)
|
// Create a new stack frame (ownership will be transferred to the caller)
|
||||||
@ -573,27 +573,4 @@ StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) {
|
|||||||
return new_frame.release();
|
return new_frame.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StackwalkerX86::ScanForReturnAddress(u_int32_t location_start,
|
|
||||||
u_int32_t *location_found,
|
|
||||||
u_int32_t *eip_found) {
|
|
||||||
const int kRASearchWords = 15;
|
|
||||||
for (u_int32_t location = location_start;
|
|
||||||
location <= location_start + kRASearchWords * 4;
|
|
||||||
location += 4) {
|
|
||||||
u_int32_t eip;
|
|
||||||
if (!memory_->GetMemoryAtAddress(location, &eip))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (modules_ && modules_->GetModuleForAddress(eip) &&
|
|
||||||
InstructionAddressSeemsValid(eip)) {
|
|
||||||
|
|
||||||
*eip_found = eip;
|
|
||||||
*location_found = location;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// nothing found
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
@ -96,19 +96,6 @@ class StackwalkerX86 : public Stackwalker {
|
|||||||
// Return NULL on failure.
|
// Return NULL on failure.
|
||||||
StackFrameX86 *GetCallerByEBPAtBase(const vector<StackFrame*> &frames);
|
StackFrameX86 *GetCallerByEBPAtBase(const vector<StackFrame*> &frames);
|
||||||
|
|
||||||
// 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 Stackwalker::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 eip_found to the value contained at that
|
|
||||||
// location in memory.
|
|
||||||
bool ScanForReturnAddress(u_int32_t location_start,
|
|
||||||
u_int32_t *location_found,
|
|
||||||
u_int32_t *eip_found);
|
|
||||||
|
|
||||||
// Stores the CPU context corresponding to the innermost stack frame to
|
// Stores the CPU context corresponding to the innermost stack frame to
|
||||||
// be returned by GetContextFrame.
|
// be returned by GetContextFrame.
|
||||||
const MDRawContextX86 *context_;
|
const MDRawContextX86 *context_;
|
||||||
|
@ -174,7 +174,7 @@ TEST_F(GetCallerFrame, Traditional) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x4000c7a5U, frame0->instruction);
|
EXPECT_EQ(0x4000c7a5U, frame0->instruction);
|
||||||
EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
|
EXPECT_EQ(0x4000c7a5U, frame0->context.eip);
|
||||||
@ -182,7 +182,7 @@ TEST_F(GetCallerFrame, Traditional) {
|
|||||||
EXPECT_EQ(NULL, frame0->windows_frame_info);
|
EXPECT_EQ(NULL, frame0->windows_frame_info);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_FP, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP),
|
| StackFrameX86::CONTEXT_VALID_EBP),
|
||||||
@ -225,7 +225,7 @@ TEST_F(GetCallerFrame, TraditionalScan) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x4000f49dU, frame0->instruction);
|
EXPECT_EQ(0x4000f49dU, frame0->instruction);
|
||||||
EXPECT_EQ(0x4000f49dU, frame0->context.eip);
|
EXPECT_EQ(0x4000f49dU, frame0->context.eip);
|
||||||
@ -234,7 +234,7 @@ TEST_F(GetCallerFrame, TraditionalScan) {
|
|||||||
EXPECT_EQ(NULL, frame0->windows_frame_info);
|
EXPECT_EQ(NULL, frame0->windows_frame_info);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_SCAN, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
|
||||||
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
|
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
|
||||||
// walker does not actually fetch the EBP after a scan (forcing the
|
// walker does not actually fetch the EBP after a scan (forcing the
|
||||||
// next frame to be scanned as well). But let's grandfather the existing
|
// next frame to be scanned as well). But let's grandfather the existing
|
||||||
@ -292,7 +292,7 @@ TEST_F(GetCallerFrame, WindowsFrameData) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x4000aa85U, frame0->instruction);
|
EXPECT_EQ(0x4000aa85U, frame0->instruction);
|
||||||
EXPECT_EQ(0x4000aa85U, frame0->context.eip);
|
EXPECT_EQ(0x4000aa85U, frame0->context.eip);
|
||||||
@ -301,7 +301,7 @@ TEST_F(GetCallerFrame, WindowsFrameData) {
|
|||||||
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP
|
| StackFrameX86::CONTEXT_VALID_EBP
|
||||||
@ -376,7 +376,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
|
|||||||
ASSERT_EQ(3U, frames->size());
|
ASSERT_EQ(3U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x40001004U, frame0->instruction);
|
EXPECT_EQ(0x40001004U, frame0->instruction);
|
||||||
EXPECT_EQ(0x40001004U, frame0->context.eip);
|
EXPECT_EQ(0x40001004U, frame0->context.eip);
|
||||||
@ -393,7 +393,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
|
|||||||
EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
|
EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_FP, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP),
|
| StackFrameX86::CONTEXT_VALID_EBP),
|
||||||
@ -412,7 +412,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) {
|
|||||||
EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
|
EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size);
|
||||||
|
|
||||||
StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
|
StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI, frame2->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP
|
| StackFrameX86::CONTEXT_VALID_EBP
|
||||||
@ -460,7 +460,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x40000c9cU, frame0->instruction);
|
EXPECT_EQ(0x40000c9cU, frame0->instruction);
|
||||||
EXPECT_EQ(0x40000c9cU, frame0->context.eip);
|
EXPECT_EQ(0x40000c9cU, frame0->context.eip);
|
||||||
@ -469,7 +469,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataScan) {
|
|||||||
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_SCAN, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
|
||||||
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
|
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker
|
||||||
// does not actually fetch the EBP after a scan (forcing the next frame
|
// does not actually fetch the EBP after a scan (forcing the next frame
|
||||||
// to be scanned as well). But let's grandfather the existing behavior in
|
// to be scanned as well). But let's grandfather the existing behavior in
|
||||||
@ -539,7 +539,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x40000700U, frame0->instruction);
|
EXPECT_EQ(0x40000700U, frame0->instruction);
|
||||||
EXPECT_EQ(0x40000700U, frame0->context.eip);
|
EXPECT_EQ(0x40000700U, frame0->context.eip);
|
||||||
@ -548,7 +548,7 @@ TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) {
|
|||||||
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
EXPECT_TRUE(frame0->windows_frame_info != NULL);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI_SCAN, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust);
|
||||||
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
|
// I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the
|
||||||
// walker does not actually fetch the EBP after a scan (forcing the
|
// walker does not actually fetch the EBP after a scan (forcing the
|
||||||
// next frame to be scanned as well). But let's grandfather the existing
|
// next frame to be scanned as well). But let's grandfather the existing
|
||||||
@ -602,7 +602,7 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x4000e8b8U, frame0->instruction);
|
EXPECT_EQ(0x4000e8b8U, frame0->instruction);
|
||||||
EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
|
EXPECT_EQ(0x4000e8b8U, frame0->context.eip);
|
||||||
@ -618,7 +618,7 @@ TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) {
|
|||||||
EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
|
EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP),
|
| StackFrameX86::CONTEXT_VALID_EBP),
|
||||||
@ -672,7 +672,7 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ(0x40009ab8U, frame0->instruction);
|
EXPECT_EQ(0x40009ab8U, frame0->instruction);
|
||||||
EXPECT_EQ(0x40009ab8U, frame0->context.eip);
|
EXPECT_EQ(0x40009ab8U, frame0->context.eip);
|
||||||
@ -689,7 +689,7 @@ TEST_F(GetCallerFrame, WindowsFPOUsedEBP) {
|
|||||||
EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
|
EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP
|
||||||
| StackFrameX86::CONTEXT_VALID_ESP
|
| StackFrameX86::CONTEXT_VALID_ESP
|
||||||
| StackFrameX86::CONTEXT_VALID_EBP),
|
| StackFrameX86::CONTEXT_VALID_EBP),
|
||||||
@ -757,7 +757,7 @@ struct CFIFixture: public StackwalkerX86Fixture {
|
|||||||
ASSERT_EQ(2U, frames->size());
|
ASSERT_EQ(2U, frames->size());
|
||||||
|
|
||||||
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CONTEXT, frame0->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
|
||||||
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity);
|
||||||
EXPECT_EQ("enchiridion", frame0->function_name);
|
EXPECT_EQ("enchiridion", frame0->function_name);
|
||||||
EXPECT_EQ(0x40004000U, frame0->function_base);
|
EXPECT_EQ(0x40004000U, frame0->function_base);
|
||||||
@ -767,7 +767,7 @@ struct CFIFixture: public StackwalkerX86Fixture {
|
|||||||
ASSERT_TRUE(frame0->cfi_frame_info != NULL);
|
ASSERT_TRUE(frame0->cfi_frame_info != NULL);
|
||||||
|
|
||||||
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1));
|
||||||
EXPECT_EQ(StackFrameX86::FRAME_TRUST_CFI, frame1->trust);
|
EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust);
|
||||||
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
|
ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP |
|
||||||
StackFrameX86::CONTEXT_VALID_ESP |
|
StackFrameX86::CONTEXT_VALID_ESP |
|
||||||
StackFrameX86::CONTEXT_VALID_EBP |
|
StackFrameX86::CONTEXT_VALID_EBP |
|
||||||
|
Loading…
x
Reference in New Issue
Block a user