2010-10-25 11:12:07 +00:00
//===-- UnwindLLDB.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/Core/Module.h"
2011-04-25 18:36:36 +00:00
# include "lldb/Core/Log.h"
2010-10-25 11:12:07 +00:00
# include "lldb/Symbol/FuncUnwinders.h"
# include "lldb/Symbol/Function.h"
# include "lldb/Symbol/UnwindPlan.h"
2015-03-03 19:23:09 +00:00
# include "lldb/Target/ABI.h"
2011-04-25 18:36:36 +00:00
# include "lldb/Target/Thread.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Process.h"
# include "lldb/Target/RegisterContext.h"
2010-10-25 11:12:07 +00:00
2011-02-15 00:19:15 +00:00
# include "UnwindLLDB.h"
# include "RegisterContextLLDB.h"
2010-10-25 11:12:07 +00:00
using namespace lldb ;
using namespace lldb_private ;
UnwindLLDB : : UnwindLLDB ( Thread & thread ) :
Unwind ( thread ) ,
2012-02-29 03:40:22 +00:00
m_frames ( ) ,
2014-02-14 05:06:49 +00:00
m_unwind_complete ( false ) ,
m_user_supplied_trap_handler_functions ( )
2010-10-25 11:12:07 +00:00
{
2014-02-14 05:06:49 +00:00
ProcessSP process_sp ( thread . GetProcess ( ) ) ;
if ( process_sp )
{
Args args ;
process_sp - > GetTarget ( ) . GetUserSpecifiedTrapHandlerNames ( args ) ;
size_t count = args . GetArgumentCount ( ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
const char * func_name = args . GetArgumentAtIndex ( i ) ;
m_user_supplied_trap_handler_functions . push_back ( ConstString ( func_name ) ) ;
}
}
2010-10-25 11:12:07 +00:00
}
uint32_t
2011-10-21 01:49:48 +00:00
UnwindLLDB : : DoGetFrameCount ( )
2010-10-25 11:12:07 +00:00
{
2012-02-29 03:40:22 +00:00
if ( ! m_unwind_complete )
2010-10-25 11:12:07 +00:00
{
2011-01-07 06:08:19 +00:00
//#define DEBUG_FRAME_SPEED 1
# if DEBUG_FRAME_SPEED
2011-01-09 21:07:35 +00:00
# define FRAME_COUNT 10000
2011-01-07 06:08:19 +00:00
TimeValue time_value ( TimeValue : : Now ( ) ) ;
# endif
2010-11-09 02:31:21 +00:00
if ( ! AddFirstFrame ( ) )
2010-10-25 11:12:07 +00:00
return 0 ;
2011-05-24 23:06:02 +00:00
2012-02-21 00:09:25 +00:00
ProcessSP process_sp ( m_thread . GetProcess ( ) ) ;
ABI * abi = process_sp ? process_sp - > GetABI ( ) . get ( ) : NULL ;
2011-05-24 23:06:02 +00:00
while ( AddOneMoreFrame ( abi ) )
2011-01-07 06:08:19 +00:00
{
# if DEBUG_FRAME_SPEED
2011-01-09 21:07:35 +00:00
if ( ( m_frames . size ( ) % FRAME_COUNT ) = = 0 )
2011-01-07 06:08:19 +00:00
{
TimeValue now ( TimeValue : : Now ( ) ) ;
uint64_t delta_t = now - time_value ;
2012-11-29 21:49:15 +00:00
printf ( " %u frames in % " PRIu64 " .%09llu ms (%g frames/sec) \n " ,
2011-01-09 21:07:35 +00:00
FRAME_COUNT ,
2011-06-18 23:52:14 +00:00
delta_t / TimeValue : : NanoSecPerSec ,
delta_t % TimeValue : : NanoSecPerSec ,
( float ) FRAME_COUNT / ( ( float ) delta_t / ( float ) TimeValue : : NanoSecPerSec ) ) ;
2011-01-07 06:08:19 +00:00
time_value = now ;
}
# endif
}
2010-11-09 02:31:21 +00:00
}
return m_frames . size ( ) ;
}
bool
UnwindLLDB : : AddFirstFrame ( )
{
2012-02-29 03:40:22 +00:00
if ( m_frames . size ( ) > 0 )
return true ;
2010-11-09 02:31:21 +00:00
// First, set up the 0th (initial) frame
CursorSP first_cursor_sp ( new Cursor ( ) ) ;
2012-01-29 20:56:30 +00:00
RegisterContextLLDBSP reg_ctx_sp ( new RegisterContextLLDB ( m_thread ,
RegisterContextLLDBSP ( ) ,
first_cursor_sp - > sctx ,
0 , * this ) ) ;
2011-05-24 23:06:02 +00:00
if ( reg_ctx_sp . get ( ) = = NULL )
2012-02-29 03:40:22 +00:00
goto unwind_done ;
2011-01-06 22:15:06 +00:00
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > IsValid ( ) )
2012-02-29 03:40:22 +00:00
goto unwind_done ;
2011-01-06 22:15:06 +00:00
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > GetCFA ( first_cursor_sp - > cfa ) )
2012-02-29 03:40:22 +00:00
goto unwind_done ;
2011-01-06 22:15:06 +00:00
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > ReadPC ( first_cursor_sp - > start_pc ) )
2012-02-29 03:40:22 +00:00
goto unwind_done ;
2011-01-06 22:15:06 +00:00
// Everything checks out, so release the auto pointer value and let the
// cursor own it in its shared pointer
2012-01-29 20:56:30 +00:00
first_cursor_sp - > reg_ctx_lldb_sp = reg_ctx_sp ;
2010-11-09 02:31:21 +00:00
m_frames . push_back ( first_cursor_sp ) ;
return true ;
2013-12-20 01:05:11 +00:00
2012-02-29 03:40:22 +00:00
unwind_done :
2013-12-20 01:05:11 +00:00
Log * log ( GetLogIfAllCategoriesSet ( LIBLLDB_LOG_UNWIND ) ) ;
if ( log )
{
log - > Printf ( " th%d Unwind of this thread is complete. " , m_thread . GetIndexID ( ) ) ;
}
2012-02-29 03:40:22 +00:00
m_unwind_complete = true ;
return false ;
2010-11-09 02:31:21 +00:00
}
2015-07-06 09:24:20 +00:00
UnwindLLDB : : CursorSP
UnwindLLDB : : GetOneMoreFrame ( ABI * abi )
2010-11-09 02:31:21 +00:00
{
2015-07-06 09:24:20 +00:00
assert ( m_frames . size ( ) ! = 0 & & " Get one more frame called with empty frame list " ) ;
2012-02-29 03:40:22 +00:00
// If we've already gotten to the end of the stack, don't bother to try again...
if ( m_unwind_complete )
2015-07-06 09:24:20 +00:00
return nullptr ;
2012-02-29 03:40:22 +00:00
2013-03-27 23:08:40 +00:00
Log * log ( GetLogIfAllCategoriesSet ( LIBLLDB_LOG_UNWIND ) ) ;
2010-11-09 02:31:21 +00:00
2015-07-06 09:24:20 +00:00
CursorSP prev_frame = m_frames . back ( ) ;
uint32_t cur_idx = m_frames . size ( ) ;
2010-11-09 02:31:21 +00:00
2015-07-06 09:24:20 +00:00
CursorSP cursor_sp ( new Cursor ( ) ) ;
2012-01-29 20:56:30 +00:00
RegisterContextLLDBSP reg_ctx_sp ( new RegisterContextLLDB ( m_thread ,
2015-07-06 09:24:20 +00:00
prev_frame - > reg_ctx_lldb_sp ,
2012-01-29 20:56:30 +00:00
cursor_sp - > sctx ,
cur_idx ,
* this ) ) ;
2013-05-03 04:48:41 +00:00
2015-07-06 09:24:20 +00:00
// We want to detect an unwind that cycles erroneously and stop backtracing.
2013-05-03 04:48:41 +00:00
// 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 blows out
// and the first 35,000 frames are uninteresting - it's the top most 5 frames that
// you actually care about. So you can't just cap the 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 ( log )
log - > Printf ( " %*sFrame %d unwound too many frames, assuming unwind has gone astray, stopping. " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2013-05-03 04:48:41 +00:00
}
2011-05-24 23:06:02 +00:00
if ( reg_ctx_sp . get ( ) = = NULL )
2013-12-20 01:05:11 +00:00
{
2014-02-21 05:20:25 +00:00
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2013-12-20 01:05:11 +00:00
if ( log )
log - > Printf ( " %*sFrame %d did not get a RegisterContext, stopping. " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2013-12-20 01:05:11 +00:00
}
2010-11-09 02:31:21 +00:00
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > IsValid ( ) )
2010-11-09 02:31:21 +00:00
{
2014-11-13 07:31:45 +00:00
// We failed to get a valid RegisterContext.
// See if the regctx below this on the stack has a fallback unwind plan it can use.
// Subsequent calls to TryFallbackUnwindPlan() will return false.
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2010-11-09 02:31:21 +00:00
if ( log )
log - > Printf ( " %*sFrame %d invalid RegisterContext for this frame, stopping stack walk " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2010-11-09 02:31:21 +00:00
}
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > GetCFA ( cursor_sp - > cfa ) )
2010-11-09 02:31:21 +00:00
{
2014-02-21 05:20:25 +00:00
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2010-11-09 02:31:21 +00:00
if ( log )
log - > Printf ( " %*sFrame %d did not get CFA for this frame, stopping stack walk " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2010-11-09 02:31:21 +00:00
}
2011-05-24 23:06:02 +00:00
if ( abi & & ! abi - > CallFrameAddressIsValid ( cursor_sp - > cfa ) )
2010-11-09 02:31:21 +00:00
{
2014-01-03 22:06:25 +00:00
// On Mac OS X, the _sigtramp asynchronous signal trampoline frame may not have
// its (constructed) CFA aligned correctly -- don't do the abi alignment check for
// these.
2014-02-13 07:11:08 +00:00
if ( reg_ctx_sp - > IsTrapHandlerFrame ( ) = = false )
2010-10-25 11:12:07 +00:00
{
2014-11-22 01:52:03 +00:00
// See if we can find a fallback unwind plan for THIS frame. It may be
// that the UnwindPlan we're using for THIS frame was bad and gave us a
// bad CFA.
// If that's not it, then see if we can change the UnwindPlan for the frame
// below us ("NEXT") -- see if using that other UnwindPlan gets us a better
// unwind state.
if ( reg_ctx_sp - > TryFallbackUnwindPlan ( ) = = false
| | reg_ctx_sp - > GetCFA ( cursor_sp - > cfa ) = = false
| | abi - > CallFrameAddressIsValid ( cursor_sp - > cfa ) = = false )
2014-02-21 05:20:25 +00:00
{
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2014-11-22 01:52:03 +00:00
if ( log )
log - > Printf ( " %*sFrame %d did not get a valid CFA for this frame, stopping stack walk " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2014-02-21 05:20:25 +00:00
}
2014-11-22 01:52:03 +00:00
else
2014-01-03 22:06:25 +00:00
{
2014-11-22 01:52:03 +00:00
if ( log )
log - > Printf ( " %*sFrame %d had a bad CFA value but we switched the UnwindPlan being used and got one that looks more realistic. " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2014-01-03 22:06:25 +00:00
}
2010-10-25 11:12:07 +00:00
}
2010-11-09 02:31:21 +00:00
}
2011-05-24 23:06:02 +00:00
if ( ! reg_ctx_sp - > ReadPC ( cursor_sp - > start_pc ) )
2010-11-09 02:31:21 +00:00
{
2014-02-21 05:20:25 +00:00
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2010-11-09 02:31:21 +00:00
if ( log )
log - > Printf ( " %*sFrame %d did not get PC for this frame, stopping stack walk " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2010-10-25 11:12:07 +00:00
}
2011-05-24 23:06:02 +00:00
if ( abi & & ! abi - > CodeAddressIsValid ( cursor_sp - > start_pc ) )
{
2014-02-21 05:20:25 +00:00
// If the RegisterContextLLDB has a fallback UnwindPlan, it will switch to that and return
// true. Subsequent calls to TryFallbackUnwindPlan() will return false.
2015-07-06 09:24:20 +00:00
if ( prev_frame - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
return GetOneMoreFrame ( abi ) ;
2011-05-24 23:06:02 +00:00
if ( log )
log - > Printf ( " %*sFrame %d did not get a valid PC, stopping stack walk " ,
cur_idx < 100 ? cur_idx : 100 , " " , cur_idx ) ;
2015-07-06 09:24:20 +00:00
return nullptr ;
2011-05-24 23:06:02 +00:00
}
2015-07-06 09:24:20 +00:00
// Infinite loop where the current cursor is the same as the previous one...
if ( prev_frame - > start_pc = = cursor_sp - > start_pc & & prev_frame - > cfa = = cursor_sp - > cfa )
2013-12-20 01:05:11 +00:00
{
2015-07-06 09:24:20 +00:00
if ( log )
log - > Printf ( " th%d pc of this frame is the same as the previous frame and CFAs for both frames are identical -- stopping unwind " , m_thread . GetIndexID ( ) ) ;
return nullptr ;
2013-12-20 01:05:11 +00:00
}
2013-09-26 14:35:59 +00:00
2012-01-29 20:56:30 +00:00
cursor_sp - > reg_ctx_lldb_sp = reg_ctx_sp ;
2015-07-06 09:24:20 +00:00
return cursor_sp ;
}
bool
UnwindLLDB : : AddOneMoreFrame ( ABI * abi )
{
Log * log ( GetLogIfAllCategoriesSet ( LIBLLDB_LOG_UNWIND ) ) ;
// Frame zero is a little different
if ( m_frames . empty ( ) )
return false ;
// If we've already gotten to the end of the stack, don't bother to try again...
if ( m_unwind_complete )
return false ;
CursorSP new_frame = m_candidate_frame ;
if ( new_frame = = nullptr )
new_frame = GetOneMoreFrame ( abi ) ;
if ( new_frame = = nullptr )
2013-12-20 01:05:11 +00:00
{
2015-07-06 09:24:20 +00:00
if ( log )
log - > Printf ( " th%d Unwind of this thread is complete. " , m_thread . GetIndexID ( ) ) ;
m_unwind_complete = true ;
return false ;
2013-12-20 01:05:11 +00:00
}
2015-07-06 09:24:20 +00:00
m_frames . push_back ( new_frame ) ;
// If we can get one more frame further then accept that we get back a correct frame.
m_candidate_frame = GetOneMoreFrame ( abi ) ;
if ( m_candidate_frame )
return true ;
// We can't go further from the frame returned by GetOneMore frame. Lets try to get a
// different frame with using the fallback unwind plan.
if ( ! m_frames [ m_frames . size ( ) - 2 ] - > reg_ctx_lldb_sp - > TryFallbackUnwindPlan ( ) )
{
// We don't have a valid fallback unwind plan. Accept the frame as it is. This is a
// valid situation when we are at the bottom of the stack.
return true ;
}
// Remove the possibly incorrect frame from the frame list and try to add a different one with
// the newly selected fallback unwind plan.
m_frames . pop_back ( ) ;
CursorSP new_frame_v2 = GetOneMoreFrame ( abi ) ;
if ( new_frame_v2 = = nullptr )
{
// We haven't got a new frame from the fallback unwind plan. Accept the frame from the
// original unwind plan. This is a valid situation when we are at the bottom of the stack.
m_frames . push_back ( new_frame ) ;
return true ;
}
// Push the new frame to the list and try to continue from this frame. If we can get a new frame
// then accept it as the correct one.
m_frames . push_back ( new_frame_v2 ) ;
m_candidate_frame = GetOneMoreFrame ( abi ) ;
if ( m_candidate_frame )
return true ;
// The new frame isn't helped in unwinding. Fall back to the original one as the default unwind
// plan is usually more reliable then the fallback one.
m_frames . pop_back ( ) ;
m_frames . push_back ( new_frame ) ;
return true ;
2010-10-25 11:12:07 +00:00
}
bool
2011-10-21 01:49:48 +00:00
UnwindLLDB : : DoGetFrameInfoAtIndex ( uint32_t idx , addr_t & cfa , addr_t & pc )
2010-10-25 11:12:07 +00:00
{
if ( m_frames . size ( ) = = 0 )
2010-11-09 02:31:21 +00:00
{
if ( ! AddFirstFrame ( ) )
return false ;
}
2012-02-21 00:09:25 +00:00
ProcessSP process_sp ( m_thread . GetProcess ( ) ) ;
ABI * abi = process_sp ? process_sp - > GetABI ( ) . get ( ) : NULL ;
2011-05-24 23:06:02 +00:00
while ( idx > = m_frames . size ( ) & & AddOneMoreFrame ( abi ) )
2010-11-09 02:31:21 +00:00
;
2010-10-25 11:12:07 +00:00
if ( idx < m_frames . size ( ) )
{
2010-11-04 00:53:20 +00:00
cfa = m_frames [ idx ] - > cfa ;
pc = m_frames [ idx ] - > start_pc ;
2010-10-25 11:12:07 +00:00
return true ;
}
return false ;
}
2011-01-06 22:15:06 +00:00
lldb : : RegisterContextSP
2013-11-04 09:33:30 +00:00
UnwindLLDB : : DoCreateRegisterContextForFrame ( StackFrame * frame )
2010-10-25 11:12:07 +00:00
{
2011-01-06 22:15:06 +00:00
lldb : : RegisterContextSP reg_ctx_sp ;
2011-01-08 01:53:06 +00:00
uint32_t idx = frame - > GetConcreteFrameIndex ( ) ;
2010-11-09 02:31:21 +00:00
2010-10-25 11:12:07 +00:00
if ( idx = = 0 )
{
return m_thread . GetRegisterContext ( ) ;
}
2010-11-09 02:31:21 +00:00
if ( m_frames . size ( ) = = 0 )
{
if ( ! AddFirstFrame ( ) )
2011-01-06 22:15:06 +00:00
return reg_ctx_sp ;
2010-11-09 02:31:21 +00:00
}
2012-02-21 00:09:25 +00:00
ProcessSP process_sp ( m_thread . GetProcess ( ) ) ;
ABI * abi = process_sp ? process_sp - > GetABI ( ) . get ( ) : NULL ;
2011-05-24 23:06:02 +00:00
2012-01-29 20:56:30 +00:00
while ( idx > = m_frames . size ( ) )
{
if ( ! AddOneMoreFrame ( abi ) )
break ;
}
2010-11-09 02:31:21 +00:00
2012-01-29 20:56:30 +00:00
const uint32_t num_frames = m_frames . size ( ) ;
if ( idx < num_frames )
{
Cursor * frame_cursor = m_frames [ idx ] . get ( ) ;
2012-02-24 01:59:29 +00:00
reg_ctx_sp = frame_cursor - > reg_ctx_lldb_sp ;
2012-01-29 20:56:30 +00:00
}
2011-01-06 22:15:06 +00:00
return reg_ctx_sp ;
2010-10-25 11:12:07 +00:00
}
2011-11-01 03:21:25 +00:00
2012-01-29 20:56:30 +00:00
UnwindLLDB : : RegisterContextLLDBSP
2011-11-01 03:21:25 +00:00
UnwindLLDB : : GetRegisterContextForFrameNum ( uint32_t frame_num )
{
2012-01-29 20:56:30 +00:00
RegisterContextLLDBSP reg_ctx_sp ;
if ( frame_num < m_frames . size ( ) )
reg_ctx_sp = m_frames [ frame_num ] - > reg_ctx_lldb_sp ;
2011-11-01 03:21:25 +00:00
return reg_ctx_sp ;
}
bool
2013-06-05 00:12:50 +00:00
UnwindLLDB : : SearchForSavedLocationForRegister ( uint32_t lldb_regnum , lldb_private : : UnwindLLDB : : RegisterLocation & regloc , uint32_t starting_frame_num , bool pc_reg )
2011-11-01 03:21:25 +00:00
{
int64_t frame_num = starting_frame_num ;
2014-04-02 03:51:35 +00:00
if ( static_cast < size_t > ( frame_num ) > = m_frames . size ( ) )
2011-11-01 03:21:25 +00:00
return false ;
2012-10-26 06:08:58 +00:00
// Never interrogate more than one level while looking for the saved pc value. If the value
// isn't saved by frame_num, none of the frames lower on the stack will have a useful value.
2013-06-05 00:12:50 +00:00
if ( pc_reg )
2012-10-26 06:08:58 +00:00
{
2012-11-16 01:03:31 +00:00
UnwindLLDB : : RegisterSearchResult result ;
result = m_frames [ frame_num ] - > reg_ctx_lldb_sp - > SavedLocationForRegister ( lldb_regnum , regloc ) ;
if ( result = = UnwindLLDB : : RegisterSearchResult : : eRegisterFound )
2012-10-26 06:08:58 +00:00
return true ;
else
return false ;
}
2011-11-01 03:21:25 +00:00
while ( frame_num > = 0 )
{
2012-11-16 01:03:31 +00:00
UnwindLLDB : : RegisterSearchResult result ;
result = m_frames [ frame_num ] - > reg_ctx_lldb_sp - > SavedLocationForRegister ( lldb_regnum , regloc ) ;
2013-01-19 03:53:42 +00:00
2014-12-09 22:28:10 +00:00
// We descended down to the live register context aka stack frame 0 and are reading the value
// out of a live register.
if ( result = = UnwindLLDB : : RegisterSearchResult : : eRegisterFound
& & regloc . type = = UnwindLLDB : : RegisterLocation : : eRegisterInLiveRegisterContext )
{
return true ;
}
2013-01-19 03:53:42 +00:00
// If we have unwind instructions saying that register N is saved in register M in the middle of
// the stack (and N can equal M here, meaning the register was not used in this function), then
// change the register number we're looking for to M and keep looking for a concrete location
// down the stack, or an actual value from a live RegisterContext at frame 0.
if ( result = = UnwindLLDB : : RegisterSearchResult : : eRegisterFound
& & regloc . type = = UnwindLLDB : : RegisterLocation : : eRegisterInRegister
& & frame_num > 0 )
{
result = UnwindLLDB : : RegisterSearchResult : : eRegisterNotFound ;
lldb_regnum = regloc . location . register_number ;
}
2012-11-16 01:03:31 +00:00
if ( result = = UnwindLLDB : : RegisterSearchResult : : eRegisterFound )
2011-11-01 03:21:25 +00:00
return true ;
2012-11-16 01:03:31 +00:00
if ( result = = UnwindLLDB : : RegisterSearchResult : : eRegisterIsVolatile )
return false ;
2011-11-01 03:21:25 +00:00
frame_num - - ;
}
return false ;
}