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