ThreadPlanCallFunction.cpp revision 6c9662e0e5840b557fcd4bd990620e106e4a18e2
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#include "llvm/Support/MachO.h" 16// Project includes 17#include "lldb/lldb-private-log.h" 18#include "lldb/Breakpoint/Breakpoint.h" 19#include "lldb/Breakpoint/BreakpointLocation.h" 20#include "lldb/Core/Address.h" 21#include "lldb/Core/Log.h" 22#include "lldb/Core/Stream.h" 23#include "lldb/Target/LanguageRuntime.h" 24#include "lldb/Target/Process.h" 25#include "lldb/Target/RegisterContext.h" 26#include "lldb/Target/StopInfo.h" 27#include "lldb/Target/Target.h" 28#include "lldb/Target/Thread.h" 29#include "lldb/Target/ThreadPlanRunToAddress.h" 30 31using namespace lldb; 32using namespace lldb_private; 33 34//---------------------------------------------------------------------- 35// ThreadPlanCallFunction: Plan to call a single function 36//---------------------------------------------------------------------- 37 38ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 39 Address &function, 40 lldb::addr_t arg, 41 bool stop_other_threads, 42 bool discard_on_error, 43 lldb::addr_t *this_arg, 44 lldb::addr_t *cmd_arg) : 45 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 46 m_valid (false), 47 m_stop_other_threads (stop_other_threads), 48 m_arg_addr (arg), 49 m_args (NULL), 50 m_process (thread.GetProcess()), 51 m_thread (thread) 52{ 53 SetOkayToDiscard (discard_on_error); 54 55 Process& process = thread.GetProcess(); 56 Target& target = process.GetTarget(); 57 const ABI *abi = process.GetABI(); 58 59 if (!abi) 60 return; 61 62 SetBreakpoints(); 63 64 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 65 66 SymbolContextList contexts; 67 SymbolContext context; 68 ModuleSP executableModuleSP (target.GetExecutableModule()); 69 70 if (!executableModuleSP || 71 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 72 return; 73 74 contexts.GetContextAtIndex(0, context); 75 76 m_start_addr = context.symbol->GetValue(); 77 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&target); 78 79 if (!thread.SaveFrameZeroState(m_register_backup)) 80 return; 81 82 m_function_addr = function; 83 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&target); 84 85 if (!abi->PrepareTrivialCall(thread, 86 spBelowRedZone, 87 FunctionLoadAddr, 88 StartLoadAddr, 89 m_arg_addr, 90 this_arg, 91 cmd_arg)) 92 return; 93 94 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 95 96 if (log) 97 { 98 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 99 100 log->PutCString("Function call was set up. Register state was:"); 101 102 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 103 register_index < num_registers; 104 ++register_index) 105 { 106 const char *register_name = reg_ctx->GetRegisterName(register_index); 107 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 108 109 log->Printf(" %s = 0x%llx", register_name, register_value); 110 } 111 } 112 113 m_valid = true; 114} 115 116ThreadPlanCallFunction::~ThreadPlanCallFunction () 117{ 118 if (m_valid && !IsPlanComplete()) 119 DoTakedown(); 120} 121 122void 123ThreadPlanCallFunction::DoTakedown () 124{ 125 m_thread.RestoreSaveFrameZero(m_register_backup); 126 m_thread.ClearStackFrames(); 127 SetPlanComplete(); 128 ClearBreakpoints(); 129} 130 131void 132ThreadPlanCallFunction::WillPop () 133{ 134 if (m_valid && !IsPlanComplete()) 135 DoTakedown(); 136} 137 138void 139ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) 140{ 141 if (level == lldb::eDescriptionLevelBrief) 142 { 143 s->Printf("Function call thread plan"); 144 } 145 else 146 { 147 if (m_args) 148 s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 149 else 150 s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process.GetTarget()), m_arg_addr); 151 } 152} 153 154bool 155ThreadPlanCallFunction::ValidatePlan (Stream *error) 156{ 157 if (!m_valid) 158 return false; 159 160 return true; 161} 162 163bool 164ThreadPlanCallFunction::PlanExplainsStop () 165{ 166 // If our subplan knows why we stopped, even if it's done (which would forward the question to us) 167 // we answer yes. 168 if(m_subplan_sp.get() != NULL && m_subplan_sp->PlanExplainsStop()) 169 return true; 170 171 // Check if the breakpoint is one of ours. 172 173 if (BreakpointsExplainStop()) 174 return true; 175 176 // If we don't want to discard this plan, than any stop we don't understand should be propagated up the stack. 177 if (!OkayToDiscard()) 178 return false; 179 180 // Otherwise, check the case where we stopped for an internal breakpoint, in that case, continue on. 181 // If it is not an internal breakpoint, consult OkayToDiscard. 182 lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); 183 184 if (stop_info_sp && stop_info_sp->GetStopReason() == eStopReasonBreakpoint) 185 { 186 uint64_t break_site_id = stop_info_sp->GetValue(); 187 lldb::BreakpointSiteSP bp_site_sp = m_thread.GetProcess().GetBreakpointSiteList().FindByID(break_site_id); 188 if (bp_site_sp) 189 { 190 uint32_t num_owners = bp_site_sp->GetNumberOfOwners(); 191 bool is_internal = true; 192 for (uint32_t i = 0; i < num_owners; i++) 193 { 194 Breakpoint &bp = bp_site_sp->GetOwnerAtIndex(i)->GetBreakpoint(); 195 196 if (!bp.IsInternal()) 197 { 198 is_internal = false; 199 break; 200 } 201 } 202 if (is_internal) 203 return false; 204 } 205 206 return OkayToDiscard(); 207 } 208 else 209 { 210 // If the subplan is running, any crashes are attributable to us. 211 return (m_subplan_sp.get() != NULL); 212 } 213} 214 215bool 216ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 217{ 218 if (PlanExplainsStop()) 219 { 220 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 221 222 if (log) 223 { 224 RegisterContext *reg_ctx = m_thread.GetRegisterContext().get(); 225 226 log->PutCString("Function completed. Register state was:"); 227 228 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 229 register_index < num_registers; 230 ++register_index) 231 { 232 const char *register_name = reg_ctx->GetRegisterName(register_index); 233 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 234 235 log->Printf(" %s = 0x%llx", register_name, register_value); 236 } 237 } 238 239 DoTakedown(); 240 241 return true; 242 } 243 else 244 { 245 return false; 246 } 247} 248 249bool 250ThreadPlanCallFunction::StopOthers () 251{ 252 return m_stop_other_threads; 253} 254 255void 256ThreadPlanCallFunction::SetStopOthers (bool new_value) 257{ 258 if (m_subplan_sp) 259 { 260 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 261 address_plan->SetStopOthers(new_value); 262 } 263 m_stop_other_threads = new_value; 264} 265 266StateType 267ThreadPlanCallFunction::GetPlanRunState () 268{ 269 return eStateRunning; 270} 271 272void 273ThreadPlanCallFunction::DidPush () 274{ 275//#define SINGLE_STEP_EXPRESSIONS 276 277#ifndef SINGLE_STEP_EXPRESSIONS 278 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 279 280 m_thread.QueueThreadPlan(m_subplan_sp, false); 281#endif 282} 283 284bool 285ThreadPlanCallFunction::WillStop () 286{ 287 return true; 288} 289 290bool 291ThreadPlanCallFunction::MischiefManaged () 292{ 293 if (IsPlanComplete()) 294 { 295 LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 296 297 if (log) 298 log->Printf("Completed call function plan."); 299 300 ThreadPlan::MischiefManaged (); 301 return true; 302 } 303 else 304 { 305 return false; 306 } 307} 308 309void 310ThreadPlanCallFunction::SetBreakpoints () 311{ 312 m_cxx_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeC_plus_plus); 313 m_objc_language_runtime = m_process.GetLanguageRuntime(eLanguageTypeObjC); 314 315 if (m_cxx_language_runtime) 316 m_cxx_language_runtime->SetExceptionBreakpoints(); 317 if (m_objc_language_runtime) 318 m_objc_language_runtime->SetExceptionBreakpoints(); 319} 320 321void 322ThreadPlanCallFunction::ClearBreakpoints () 323{ 324 if (m_cxx_language_runtime) 325 m_cxx_language_runtime->ClearExceptionBreakpoints(); 326 if (m_objc_language_runtime) 327 m_objc_language_runtime->ClearExceptionBreakpoints(); 328} 329 330bool 331ThreadPlanCallFunction::BreakpointsExplainStop() 332{ 333 lldb::StopInfoSP stop_info_sp = GetPrivateStopReason(); 334 335 if (m_cxx_language_runtime && 336 m_cxx_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) 337 return true; 338 339 if (m_objc_language_runtime && 340 m_objc_language_runtime->ExceptionBreakpointsExplainStop(stop_info_sp)) 341 return true; 342 343 return false; 344} 345