diff options
author | Jason Molenda <jmolenda@apple.com> | 2011-10-18 02:57:27 +0000 |
---|---|---|
committer | Jason Molenda <jmolenda@apple.com> | 2011-10-18 02:57:27 +0000 |
commit | e858e332000103a3b9499c70f88b79dafc69f65f (patch) | |
tree | 1f27a754c0e5396a4e77d1187394dd6b71365ed1 | |
parent | f333f8c40df86381db23105973587bcfdbca97a5 (diff) | |
download | bcm5719-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.cpp | 39 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/Utility/RegisterContextLLDB.h | 3 |
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. |