summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2011-10-18 02:57:27 +0000
committerJason Molenda <jmolenda@apple.com>2011-10-18 02:57:27 +0000
commite858e332000103a3b9499c70f88b79dafc69f65f (patch)
tree1f27a754c0e5396a4e77d1187394dd6b71365ed1
parentf333f8c40df86381db23105973587bcfdbca97a5 (diff)
downloadbcm5719-llvm-e858e332000103a3b9499c70f88b79dafc69f65f.tar.gz
bcm5719-llvm-e858e332000103a3b9499c70f88b79dafc69f65f.zip
Add code to RegisterContextLLDB::InitializeNonZerothFrame to detect a multiple stack frames
with the same CFA (or an alternating sequence between two CFA values) to catch a handful of unwind cases where lldb will inf loop trying to unwind a stack. llvm-svn: 142331
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp39
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h3
2 files changed, 42 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
index ed3ab14ac3b..5851a843144 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -448,6 +448,38 @@ RegisterContextLLDB::InitializeNonZerothFrame()
return;
}
+ // If we have a bad stack setup, we can get the same CFA value multiple times -- or even
+ // more devious, we can actually oscillate between two CFA values. Detect that here and
+ // break out to avoid a possible infinite loop in lldb trying to unwind the stack.
+ addr_t next_frame_cfa;
+ addr_t next_next_frame_cfa = LLDB_INVALID_ADDRESS;
+ if (m_next_frame.get() && m_next_frame->GetCFA(next_frame_cfa))
+ {
+ bool repeating_frames = false;
+ if (next_frame_cfa == m_cfa)
+ {
+ repeating_frames = true;
+ }
+ else
+ {
+ if (m_next_frame->GetNextFrame() && m_next_frame->GetNextFrame()->GetCFA(next_next_frame_cfa)
+ && next_next_frame_cfa == m_cfa)
+ {
+ repeating_frames = true;
+ }
+ }
+ if (repeating_frames)
+ {
+ if (log)
+ {
+ log->Printf("%*sFrame %u same CFA address as next frame, assuming the unwind is looping - stopping",
+ m_frame_number < 100 ? m_frame_number : 100, "", m_frame_number);
+ }
+ m_frame_type = eNotAValidFrame;
+ return;
+ }
+ }
+
if (log)
{
log->Printf("%*sFrame %u initialized frame current pc is 0x%llx cfa is 0x%llx",
@@ -1219,6 +1251,13 @@ RegisterContextLLDB::GetCFA (addr_t& cfa)
return true;
}
+
+RegisterContextLLDB::SharedPtr
+RegisterContextLLDB::GetNextFrame ()
+{
+ return m_next_frame;
+}
+
// Retrieve the address of the start of the function of THIS frame
bool
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
index b255636291a..5d89b8ef34a 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h
@@ -122,6 +122,9 @@ private:
void
InitializeNonZerothFrame();
+ SharedPtr
+ GetNextFrame ();
+
// Provide a location for where THIS function saved the CALLER's register value
// Or a frame "below" this one saved it, i.e. a function called by this one, preserved a register that this
// function didn't modify/use.
OpenPOWER on IntegriCloud