aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-01-24 19:59:09 +0000
committerted.mielczarek <ted.mielczarek@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-01-24 19:59:09 +0000
commit281d52d944d63ddfbe933a7bbe8adbfba3523966 (patch)
treec0d1d840bbd1c26f8adecdf4a15e6c7e428b48d8 /src
parentFix clang warning / miscompile. (diff)
downloadbreakpad-281d52d944d63ddfbe933a7bbe8adbfba3523966.tar.xz
Fix some apparently longstanding crash bugs in Stackwalker implementations when resolver is NULL.
R=mark at http://breakpad.appspot.com/257001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@761 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src')
-rw-r--r--src/processor/stackwalker.cc3
-rw-r--r--src/processor/stackwalker_amd64.cc2
-rw-r--r--src/processor/stackwalker_amd64_unittest.cc28
-rw-r--r--src/processor/stackwalker_arm.cc4
-rw-r--r--src/processor/stackwalker_arm_unittest.cc24
-rw-r--r--src/processor/stackwalker_x86.cc5
-rw-r--r--src/processor/stackwalker_x86_unittest.cc22
7 files changed, 75 insertions, 13 deletions
diff --git a/src/processor/stackwalker.cc b/src/processor/stackwalker.cc
index b0f0c4b2..9ddb60ae 100644
--- a/src/processor/stackwalker.cc
+++ b/src/processor/stackwalker.cc
@@ -120,7 +120,8 @@ bool Stackwalker::Walk(CallStack *stack) {
if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule())
supplier_->FreeSymbolData(module);
}
- resolver_->FillSourceLineInfo(frame.get());
+ if (resolver_)
+ resolver_->FillSourceLineInfo(frame.get());
}
}
diff --git a/src/processor/stackwalker_amd64.cc b/src/processor/stackwalker_amd64.cc
index c142e2a3..fd9ccdf3 100644
--- a/src/processor/stackwalker_amd64.cc
+++ b/src/processor/stackwalker_amd64.cc
@@ -184,7 +184,7 @@ StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack *stack) {
// If we have DWARF CFI information, use it.
scoped_ptr<CFIFrameInfo> cfi_frame_info(
- resolver_->FindCFIFrameInfo(last_frame));
+ resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL);
if (cfi_frame_info.get())
new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
diff --git a/src/processor/stackwalker_amd64_unittest.cc b/src/processor/stackwalker_amd64_unittest.cc
index 758c06db..0cb5fd57 100644
--- a/src/processor/stackwalker_amd64_unittest.cc
+++ b/src/processor/stackwalker_amd64_unittest.cc
@@ -130,6 +130,28 @@ class StackwalkerAMD64Fixture {
class GetContextFrame: public StackwalkerAMD64Fixture, public Test { };
+class SanityCheck: public StackwalkerAMD64Fixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ // There should be no references to the stack in this walk: we don't
+ // provide any call frame information, so trying to reconstruct the
+ // context frame's caller should fail. So there's no need for us to
+ // provide stack contents.
+ raw_context.rip = 0x40000000c0000200ULL;
+ raw_context.rbp = 0x8000000080000000ULL;
+
+ StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
+ NULL, NULL);
+ // This should succeed even without a resolver or supplier.
+ ASSERT_TRUE(walker.Walk(&call_stack));
+ frames = call_stack.frames();
+ ASSERT_GE(1U, frames->size());
+ StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
TEST_F(GetContextFrame, Simple) {
// There should be no references to the stack in this walk: we don't
// provide any call frame information, so trying to reconstruct the
@@ -139,14 +161,14 @@ TEST_F(GetContextFrame, Simple) {
raw_context.rbp = 0x8000000080000000ULL;
StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules,
- &supplier, &resolver);
+ &supplier, &resolver);
ASSERT_TRUE(walker.Walk(&call_stack));
frames = call_stack.frames();
ASSERT_GE(1U, frames->size());
StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0));
// Check that the values from the original raw context made it
// through to the context in the stack frame.
- EXPECT_TRUE(memcmp(&raw_context, &frame->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
}
class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { };
@@ -195,7 +217,7 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
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);
- EXPECT_TRUE(memcmp(&raw_context, &frame0->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
diff --git a/src/processor/stackwalker_arm.cc b/src/processor/stackwalker_arm.cc
index 239f89d0..3b91caff 100644
--- a/src/processor/stackwalker_arm.cc
+++ b/src/processor/stackwalker_arm.cc
@@ -190,8 +190,8 @@ StackFrame* StackwalkerARM::GetCallerFrame(const CallStack *stack) {
scoped_ptr<StackFrameARM> frame;
// See if there is DWARF call frame information covering this address.
- scoped_ptr<CFIFrameInfo> cfi_frame_info(resolver_
- ->FindCFIFrameInfo(last_frame));
+ scoped_ptr<CFIFrameInfo> cfi_frame_info(
+ resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL);
if (cfi_frame_info.get())
frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get()));
diff --git a/src/processor/stackwalker_arm_unittest.cc b/src/processor/stackwalker_arm_unittest.cc
index 637435b1..cb7ce631 100644
--- a/src/processor/stackwalker_arm_unittest.cc
+++ b/src/processor/stackwalker_arm_unittest.cc
@@ -130,6 +130,24 @@ class StackwalkerARMFixture {
const vector<StackFrame *> *frames;
};
+class SanityCheck: public StackwalkerARMFixture, public Test { };
+
+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.
+ StackwalkerARM walker(&system_info, &raw_context, &stack_region, &modules,
+ NULL, NULL);
+ // This should succeed even without a resolver or supplier.
+ ASSERT_TRUE(walker.Walk(&call_stack));
+ frames = call_stack.frames();
+ ASSERT_EQ(1U, frames->size());
+ StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
class GetContextFrame: public StackwalkerARMFixture, public Test { };
TEST_F(GetContextFrame, Simple) {
@@ -144,7 +162,7 @@ TEST_F(GetContextFrame, Simple) {
StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0));
// Check that the values from the original raw context made it
// through to the context in the stack frame.
- EXPECT_TRUE(memcmp(&raw_context, &frame->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
}
class GetCallerFrame: public StackwalkerARMFixture, public Test { };
@@ -192,7 +210,7 @@ TEST_F(GetCallerFrame, ScanWithoutSymbols) {
StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
- EXPECT_TRUE(memcmp(&raw_context, &frame0->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1));
EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust);
@@ -255,7 +273,7 @@ TEST_F(GetCallerFrame, ScanWithFunctionSymbols) {
StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0));
EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust);
ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity);
- EXPECT_TRUE(memcmp(&raw_context, &frame0->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context)));
EXPECT_EQ("monotreme", frame0->function_name);
EXPECT_EQ(0x40000100, frame0->function_base);
diff --git a/src/processor/stackwalker_x86.cc b/src/processor/stackwalker_x86.cc
index 9440f1d5..2ee37bfb 100644
--- a/src/processor/stackwalker_x86.cc
+++ b/src/processor/stackwalker_x86.cc
@@ -531,13 +531,14 @@ StackFrame *StackwalkerX86::GetCallerFrame(const CallStack *stack) {
// If the resolver has Windows stack walking information, use that.
WindowsFrameInfo *windows_frame_info
- = resolver_->FindWindowsFrameInfo(last_frame);
+ = resolver_ ? resolver_->FindWindowsFrameInfo(last_frame) : NULL;
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_->FindCFIFrameInfo(last_frame);
+ CFIFrameInfo *cfi_frame_info =
+ resolver_ ? resolver_->FindCFIFrameInfo(last_frame) : NULL;
if (cfi_frame_info)
new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info));
}
diff --git a/src/processor/stackwalker_x86_unittest.cc b/src/processor/stackwalker_x86_unittest.cc
index aece4891..aa6b6310 100644
--- a/src/processor/stackwalker_x86_unittest.cc
+++ b/src/processor/stackwalker_x86_unittest.cc
@@ -129,6 +129,26 @@ class StackwalkerX86Fixture {
const vector<StackFrame *> *frames;
};
+class SanityCheck: public StackwalkerX86Fixture, public Test { };
+
+TEST_F(SanityCheck, NoResolver) {
+ stack_section.start() = 0x80000000;
+ stack_section.D32(0).D32(0); // end-of-stack marker
+ RegionFromSection();
+ raw_context.eip = 0x40000200;
+ raw_context.ebp = 0x80000000;
+
+ StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules,
+ NULL, NULL);
+ // This should succeed, even without a resolver or supplier.
+ ASSERT_TRUE(walker.Walk(&call_stack));
+ frames = call_stack.frames();
+ StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
+ // Check that the values from the original raw context made it
+ // through to the context in the stack frame.
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
+}
+
class GetContextFrame: public StackwalkerX86Fixture, public Test { };
TEST_F(GetContextFrame, Simple) {
@@ -145,7 +165,7 @@ TEST_F(GetContextFrame, Simple) {
StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0));
// Check that the values from the original raw context made it
// through to the context in the stack frame.
- EXPECT_TRUE(memcmp(&raw_context, &frame->context, sizeof(raw_context)) == 0);
+ EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context)));
}
class GetCallerFrame: public StackwalkerX86Fixture, public Test { };