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 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 39 m_valid (false), 40 m_stop_other_threads (stop_other_threads), 41 m_arg_addr (arg), 42 m_args (NULL), 43 m_process (thread.GetProcess()), 44 m_thread (thread) 45 { 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(&process); 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(&process); 76 77 if (!abi->PrepareTrivialCall(thread, 78 spBelowRedZone, 79 FunctionLoadAddr, 80 StartLoadAddr, 81 m_arg_addr)) 82 return; 83 84 m_valid = true; 85 } 86 87 ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 88 Address &function, 89 ValueList &args, 90 bool stop_other_threads, 91 bool discard_on_error) : 92 ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 93 m_valid (false), 94 m_stop_other_threads (stop_other_threads), 95 m_arg_addr (0), 96 m_args (&args), 97 m_process (thread.GetProcess()), 98 m_thread (thread) 99 { 100 101 SetOkayToDiscard (discard_on_error); 102 103 Process& process = thread.GetProcess(); 104 Target& target = process.GetTarget(); 105 const ABI *abi = process.GetABI(); 106 107 if(!abi) 108 return; 109 110 lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 111 112 SymbolContextList contexts; 113 SymbolContext context; 114 ModuleSP executableModuleSP (target.GetExecutableModule()); 115 116 if (!executableModuleSP || 117 !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 118 return; 119 120 contexts.GetContextAtIndex(0, context); 121 122 m_start_addr = context.symbol->GetValue(); 123 lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process); 124 125 if(!thread.SaveFrameZeroState(m_register_backup)) 126 return; 127 128 m_function_addr = function; 129 lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process); 130 131 if (!abi->PrepareNormalCall(thread, 132 spBelowRedZone, 133 FunctionLoadAddr, 134 StartLoadAddr, 135 *m_args)) 136 return; 137 138 m_valid = true; 139 } 140 141 ThreadPlanCallFunction::~ThreadPlanCallFunction () 142 { 143 } 144 145 void 146 ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) 147 { 148 if (level == lldb::eDescriptionLevelBrief) 149 { 150 s->Printf("Function call thread plan"); 151 } 152 else 153 { 154 if (m_args) 155 s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process), m_arg_addr); 156 else 157 s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process), m_arg_addr); 158 } 159 } 160 161 bool 162 ThreadPlanCallFunction::ValidatePlan (Stream *error) 163 { 164 if (!m_valid) 165 return false; 166 167 return true; 168 } 169 170 bool 171 ThreadPlanCallFunction::PlanExplainsStop () 172 { 173 if (!m_subplan_sp) 174 return false; 175 else 176 return m_subplan_sp->PlanExplainsStop(); 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