ThreadPlanCallFunction.cpp revision 1af4e79959e941568390b867fb14cfedc7d6919f
1//===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "lldb/Target/ThreadPlanCallFunction.h" 11 12// C Includes 13// C++ Includes 14// Other libraries and framework includes 15// Project includes 16#include "lldb/lldb-private-log.h" 17#include "lldb/Core/Address.h" 18#include "lldb/Core/Log.h" 19#include "lldb/Core/Stream.h" 20#include "lldb/Target/Process.h" 21#include "lldb/Target/RegisterContext.h" 22#include "lldb/Target/Target.h" 23#include "lldb/Target/Thread.h" 24#include "lldb/Target/ThreadPlanRunToAddress.h" 25 26using namespace lldb; 27using namespace lldb_private; 28 29//---------------------------------------------------------------------- 30// ThreadPlanCallFunction: Plan to call a single function 31//---------------------------------------------------------------------- 32 33ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 34 Address &function, 35 lldb::addr_t arg, 36 bool stop_other_threads, 37 bool discard_on_error, 38 lldb::addr_t *this_arg) : 39 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 40 m_valid (false), 41 m_stop_other_threads (stop_other_threads), 42 m_arg_addr (arg), 43 m_args (NULL), 44 m_process (thread.GetProcess()), 45 m_thread (thread) 46{ 47 SetOkayToDiscard (discard_on_error); 48 49 Process& process = thread.GetProcess(); 50 Target& target = process.GetTarget(); 51 const ABI *abi = process.GetABI(); 52 53 if (!abi) 54 return; 55 56 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 57 58 SymbolContextList contexts; 59 SymbolContext context; 60 ModuleSP executableModuleSP (target.GetExecutableModule()); 61 62 if (!executableModuleSP || 63 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 64 return; 65 66 contexts.GetContextAtIndex(0, context); 67 68 m_start_addr = context.symbol->GetValue(); 69 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); 70 71 if (!thread.SaveFrameZeroState(m_register_backup)) 72 return; 73 74 m_function_addr = function; 75 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); 76 77 if (!abi->PrepareTrivialCall(thread, 78 spBelowRedZone, 79 FunctionLoadAddr, 80 StartLoadAddr, 81 m_arg_addr, 82 this_arg)) 83 return; 84 85 m_valid = true; 86} 87 88ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 89 Address &function, 90 ValueList &args, 91 bool stop_other_threads, 92 bool discard_on_error) : 93 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 94 m_valid (false), 95 m_stop_other_threads (stop_other_threads), 96 m_arg_addr (0), 97 m_args (&args), 98 m_process (thread.GetProcess()), 99 m_thread (thread) 100{ 101 102 SetOkayToDiscard (discard_on_error); 103 104 Process& process = thread.GetProcess(); 105 Target& target = process.GetTarget(); 106 const ABI *abi = process.GetABI(); 107 108 if(!abi) 109 return; 110 111 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 112 113 SymbolContextList contexts; 114 SymbolContext context; 115 ModuleSP executableModuleSP (target.GetExecutableModule()); 116 117 if (!executableModuleSP || 118 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 119 return; 120 121 contexts.GetContextAtIndex(0, context); 122 123 m_start_addr = context.symbol->GetValue(); 124 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); 125 126 if(!thread.SaveFrameZeroState(m_register_backup)) 127 return; 128 129 m_function_addr = function; 130 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); 131 132 if (!abi->PrepareNormalCall(thread, 133 spBelowRedZone, 134 FunctionLoadAddr, 135 StartLoadAddr, 136 *m_args)) 137 return; 138 139 m_valid = true; 140} 141 142ThreadPlanCallFunction::~ThreadPlanCallFunction () 143{ 144} 145 146void 147ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) 148{ 149 if (level == lldb::eDescriptionLevelBrief) 150 { 151 s->Printf("Function call thread plan"); 152 } 153 else 154 { 155 if (m_args) 156 s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 157 else 158 s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 159 } 160} 161 162bool 163ThreadPlanCallFunction::ValidatePlan (Stream *error) 164{ 165 if (!m_valid) 166 return false; 167 168 return true; 169} 170 171bool 172ThreadPlanCallFunction::PlanExplainsStop () 173{ 174 // If the subplan is running, any crashes are attributable to us. 175 176 return (m_subplan_sp.get() != NULL); 177} 178 179bool 180ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 181{ 182 if (PlanExplainsStop()) 183 { 184 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 185 186 if (log) 187 { 188 RegisterContext *reg_ctx = m_thread.GetRegisterContext(); 189 190 log->PutCString("Function completed. Register state was:"); 191 192 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 193 register_index < num_registers; 194 ++register_index) 195 { 196 const char *register_name = reg_ctx->GetRegisterName(register_index); 197 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 198 199 log->Printf(" %s = 0x%llx", register_name, register_value); 200 } 201 } 202 203 m_thread.RestoreSaveFrameZero(m_register_backup); 204 m_thread.ClearStackFrames(); 205 SetPlanComplete(); 206 return true; 207 } 208 else 209 { 210 return false; 211 } 212} 213 214bool 215ThreadPlanCallFunction::StopOthers () 216{ 217 return m_stop_other_threads; 218} 219 220void 221ThreadPlanCallFunction::SetStopOthers (bool new_value) 222{ 223 if (m_subplan_sp) 224 { 225 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 226 address_plan->SetStopOthers(new_value); 227 } 228 m_stop_other_threads = new_value; 229} 230 231StateType 232ThreadPlanCallFunction::RunState () 233{ 234 return eStateRunning; 235} 236 237void 238ThreadPlanCallFunction::DidPush () 239{ 240 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 241 242 m_thread.QueueThreadPlan(m_subplan_sp, false); 243 244} 245 246bool 247ThreadPlanCallFunction::WillStop () 248{ 249 return true; 250} 251 252bool 253ThreadPlanCallFunction::MischiefManaged () 254{ 255 if (IsPlanComplete()) 256 { 257 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 258 259 if (log) 260 log->Printf("Completed call function plan."); 261 262 ThreadPlan::MischiefManaged (); 263 return true; 264 } 265 else 266 { 267 return false; 268 } 269} 270