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 26 using namespace lldb; 27 using namespace lldb_private; 28 29 //---------------------------------------------------------------------- 30 // ThreadPlanCallFunction: Plan to call a single function 31 //---------------------------------------------------------------------- 32 33 ThreadPlanCallFunction::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 88 ThreadPlanCallFunction::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 142 ThreadPlanCallFunction::~ThreadPlanCallFunction () 143 { 144 } 145 146 void 147 ThreadPlanCallFunction::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 162 bool 163 ThreadPlanCallFunction::ValidatePlan (Stream *error) 164 { 165 if (!m_valid) 166 return false; 167 168 return true; 169 } 170 171 bool 172 ThreadPlanCallFunction::PlanExplainsStop () 173 { 174 // If the subplan is running, any crashes are attributable to us. 175 176 return (m_subplan_sp.get() != NULL); 177 } 178 179 bool 180 ThreadPlanCallFunction::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 214 bool 215 ThreadPlanCallFunction::StopOthers () 216 { 217 return m_stop_other_threads; 218 } 219 220 void 221 ThreadPlanCallFunction::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 231 StateType 232 ThreadPlanCallFunction::RunState () 233 { 234 return eStateRunning; 235 } 236 237 void 238 ThreadPlanCallFunction::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 246 bool 247 ThreadPlanCallFunction::WillStop () 248 { 249 return true; 250 } 251 252 bool 253 ThreadPlanCallFunction::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