Change the unwinder to not use a hard-coded limit on the
max number of stack frames to backtrace, make it a setting, target.process.thread.max-backtrace-depth. Add a test case for the setting. <rdar://problem/28759559> llvm-svn: 343029
This commit is contained in:
parent
b1e3d45318
commit
a11b3fe26f
|
@ -57,6 +57,8 @@ public:
|
|||
bool GetStepInAvoidsNoDebug() const;
|
||||
|
||||
bool GetStepOutAvoidsNoDebug() const;
|
||||
|
||||
uint64_t GetMaxBacktraceDepth() const;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<ThreadProperties> ThreadPropertiesSP;
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
LEVEL = ../../../make
|
||||
|
||||
CXXFLAGS += -std=c++11
|
||||
CXX_SOURCES := main.cpp
|
||||
ENABLE_THREADS := YES
|
||||
include $(LEVEL)/Makefile.rules
|
|
@ -0,0 +1,31 @@
|
|||
"""
|
||||
Test that the target.process.thread.max-backtrace-depth setting works.
|
||||
"""
|
||||
|
||||
import unittest2
|
||||
import lldb
|
||||
from lldbsuite.test.decorators import *
|
||||
from lldbsuite.test.lldbtest import *
|
||||
from lldbsuite.test import lldbutil
|
||||
|
||||
|
||||
class BacktraceLimitSettingTest(TestBase):
|
||||
|
||||
mydir = TestBase.compute_mydir(__file__)
|
||||
NO_DEBUG_INFO_TESTCASE = True
|
||||
|
||||
def setUp(self):
|
||||
# Call super's setUp().
|
||||
TestBase.setUp(self)
|
||||
|
||||
def test_backtrace_depth(self):
|
||||
"""Test that the max-backtrace-depth setting limits backtraces."""
|
||||
self.build()
|
||||
self.main_source_file = lldb.SBFileSpec("main.cpp")
|
||||
(target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self,
|
||||
"Set a breakpoint here", self.main_source_file)
|
||||
interp = self.dbg.GetCommandInterpreter()
|
||||
result = lldb.SBCommandReturnObject()
|
||||
interp.HandleCommand("settings set target.process.thread.max-backtrace-depth 30", result)
|
||||
self.assertEqual(True, result.Succeeded())
|
||||
self.assertEqual(30, thread.GetNumFrames())
|
|
@ -0,0 +1,13 @@
|
|||
int bottom () {
|
||||
return 1; // Set a breakpoint here
|
||||
}
|
||||
int foo(int in) {
|
||||
if (in > 0)
|
||||
return foo(--in) + 5;
|
||||
else
|
||||
return bottom();
|
||||
}
|
||||
int main()
|
||||
{
|
||||
return foo(500);
|
||||
}
|
|
@ -130,6 +130,8 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
|
|||
RegisterContextLLDBSP reg_ctx_sp(new RegisterContextLLDB(
|
||||
m_thread, prev_frame->reg_ctx_lldb_sp, cursor_sp->sctx, cur_idx, *this));
|
||||
|
||||
uint64_t max_stack_depth = m_thread.GetMaxBacktraceDepth();
|
||||
|
||||
// We want to detect an unwind that cycles erroneously and stop backtracing.
|
||||
// Don't want this maximum unwind limit to be too low -- if you have a
|
||||
// backtrace with an "infinitely recursing" bug, it will crash when the stack
|
||||
|
@ -138,7 +140,7 @@ UnwindLLDB::CursorSP UnwindLLDB::GetOneMoreFrame(ABI *abi) {
|
|||
// unwind at 10,000 or something. Realistically anything over around 200,000
|
||||
// is going to blow out the stack space. If we're still unwinding at that
|
||||
// point, we're probably never going to finish.
|
||||
if (cur_idx > 300000) {
|
||||
if (cur_idx >= max_stack_depth) {
|
||||
if (log)
|
||||
log->Printf("%*sFrame %d unwound too many frames, assuming unwind has "
|
||||
"gone astray, stopping.",
|
||||
|
|
|
@ -80,6 +80,8 @@ static PropertyDefinition g_properties[] = {
|
|||
nullptr, "A list of libraries that source stepping won't stop in."},
|
||||
{"trace-thread", OptionValue::eTypeBoolean, false, false, nullptr, nullptr,
|
||||
"If true, this thread will single-step and log execution."},
|
||||
{"max-backtrace-depth", OptionValue::eTypeUInt64, false, 300000, nullptr,
|
||||
nullptr, "Maximum number of frames to backtrace."},
|
||||
{nullptr, OptionValue::eTypeInvalid, false, 0, nullptr, nullptr, nullptr}};
|
||||
|
||||
enum {
|
||||
|
@ -87,7 +89,8 @@ enum {
|
|||
ePropertyStepOutAvoidsNoDebug,
|
||||
ePropertyStepAvoidRegex,
|
||||
ePropertyStepAvoidLibraries,
|
||||
ePropertyEnableThreadTrace
|
||||
ePropertyEnableThreadTrace,
|
||||
ePropertyMaxBacktraceDepth
|
||||
};
|
||||
|
||||
class ThreadOptionValueProperties : public OptionValueProperties {
|
||||
|
@ -165,6 +168,12 @@ bool ThreadProperties::GetStepOutAvoidsNoDebug() const {
|
|||
nullptr, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
uint64_t ThreadProperties::GetMaxBacktraceDepth() const {
|
||||
const uint32_t idx = ePropertyMaxBacktraceDepth;
|
||||
return m_collection_sp->GetPropertyAtIndexAsUInt64(
|
||||
nullptr, idx, g_properties[idx].default_uint_value != 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Thread Event Data
|
||||
//------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue