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_process(thread.GetProcess()), 41 m_arg_addr (arg), 42 m_args (NULL), 43 m_thread(thread), 44 m_stop_other_threads(stop_other_threads) 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_process(thread.GetProcess()), 95 m_arg_addr (0), 96 m_args (&args), 97 m_thread(thread), 98 m_stop_other_threads(stop_other_threads) 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 m_thread.RestoreSaveFrameZero(m_register_backup); 185 m_thread.ClearStackFrames(); 186 SetPlanComplete(); 187 return true; 188 } 189 else 190 { 191 return false; 192 } 193 } 194 195 bool 196 ThreadPlanCallFunction::StopOthers () 197 { 198 return m_stop_other_threads; 199 } 200 201 void 202 ThreadPlanCallFunction::SetStopOthers (bool new_value) 203 { 204 if (m_subplan_sp) 205 { 206 ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 207 address_plan->SetStopOthers(new_value); 208 } 209 m_stop_other_threads = new_value; 210 } 211 212 StateType 213 ThreadPlanCallFunction::RunState () 214 { 215 return eStateRunning; 216 } 217 218 void 219 ThreadPlanCallFunction::DidPush () 220 { 221 m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 222 223 m_thread.QueueThreadPlan(m_subplan_sp, false); 224 225 } 226 227 bool 228 ThreadPlanCallFunction::WillStop () 229 { 230 return true; 231 } 232 233 bool 234 ThreadPlanCallFunction::MischiefManaged () 235 { 236 if (IsPlanComplete()) 237 { 238 Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 239 240 if (log) 241 log->Printf("Completed call function plan."); 242 243 ThreadPlan::MischiefManaged (); 244 return true; 245 } 246 else 247 { 248 return false; 249 } 250 } 251