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 if (!m_subplan_sp) 179 return false; 180 else 181 return m_subplan_sp->PlanExplainsStop(); 182 } 183 184 bool 185 ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 186 { 187 if (PlanExplainsStop()) 188 { 189 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 190 191 if (log) 192 { 193 RegisterContext *reg_ctx = m_thread.GetRegisterContext(); 194 195 log->PutCString("Function completed. Register state was:"); 196 197 for (uint32_t register_index = 0, num_registers = reg_ctx->GetRegisterCount(); 198 register_index < num_registers; 199 ++register_index) 200 { 201 const char *register_name = reg_ctx->GetRegisterName(register_index); 202 uint64_t register_value = reg_ctx->ReadRegisterAsUnsigned(register_index, LLDB_INVALID_ADDRESS); 203 204 log->Printf(" %s = 0x%llx", register_name, register_value); 205 } 206 } 207 208 m_thread.RestoreSaveFrameZero(m_register_backup); 209 m_thread.ClearStackFrames(); 210 SetPlanComplete(); 211 return true; 212 } 213 else 214 { 215 return false; 216 } 217 } 218 219 bool 220 ThreadPlanCallFunction::StopOthers () 221 { 222 return m_stop_other_threads; 223 } 224 225 void 226 ThreadPlanCallFunction::SetStopOthers (bool new_value) 227 { 228 if (m_subplan_sp) 229 { 230 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 231 address_plan->SetStopOthers(new_value); 232 } 233 m_stop_other_threads = new_value; 234 } 235 236 StateType 237 ThreadPlanCallFunction::RunState () 238 { 239 return eStateRunning; 240 } 241 242 void 243 ThreadPlanCallFunction::DidPush () 244 { 245 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 246 247 m_thread.QueueThreadPlan(m_subplan_sp, false); 248 249 } 250 251 bool 252 ThreadPlanCallFunction::WillStop () 253 { 254 return true; 255 } 256 257 bool 258 ThreadPlanCallFunction::MischiefManaged () 259 { 260 if (IsPlanComplete()) 261 { 262 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 263 264 if (log) 265 log->Printf("Completed call function plan."); 266 267 ThreadPlan::MischiefManaged (); 268 return true; 269 } 270 else 271 { 272 return false; 273 } 274 } 275