1*30fdc8d8SChris Lattner //===-- ThreadPlanCallFunction.cpp ------------------------------*- C++ -*-===// 2*30fdc8d8SChris Lattner // 3*30fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 4*30fdc8d8SChris Lattner // 5*30fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 6*30fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 7*30fdc8d8SChris Lattner // 8*30fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 9*30fdc8d8SChris Lattner 10*30fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanCallFunction.h" 11*30fdc8d8SChris Lattner 12*30fdc8d8SChris Lattner // C Includes 13*30fdc8d8SChris Lattner // C++ Includes 14*30fdc8d8SChris Lattner // Other libraries and framework includes 15*30fdc8d8SChris Lattner // Project includes 16*30fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 17*30fdc8d8SChris Lattner #include "lldb/Core/Address.h" 18*30fdc8d8SChris Lattner #include "lldb/Core/Log.h" 19*30fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 20*30fdc8d8SChris Lattner #include "lldb/Target/Process.h" 21*30fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 22*30fdc8d8SChris Lattner #include "lldb/Target/Target.h" 23*30fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 24*30fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h" 25*30fdc8d8SChris Lattner 26*30fdc8d8SChris Lattner using namespace lldb; 27*30fdc8d8SChris Lattner using namespace lldb_private; 28*30fdc8d8SChris Lattner 29*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 30*30fdc8d8SChris Lattner // ThreadPlanCallFunction: Plan to call a single function 31*30fdc8d8SChris Lattner //---------------------------------------------------------------------- 32*30fdc8d8SChris Lattner 33*30fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 34*30fdc8d8SChris Lattner Address &function, 35*30fdc8d8SChris Lattner lldb::addr_t arg, 36*30fdc8d8SChris Lattner bool stop_other_threads, 37*30fdc8d8SChris Lattner bool discard_on_error) : 38*30fdc8d8SChris Lattner ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 39*30fdc8d8SChris Lattner m_valid(false), 40*30fdc8d8SChris Lattner m_process(thread.GetProcess()), 41*30fdc8d8SChris Lattner m_arg_addr (arg), 42*30fdc8d8SChris Lattner m_args (NULL), 43*30fdc8d8SChris Lattner m_thread(thread), 44*30fdc8d8SChris Lattner m_stop_other_threads(stop_other_threads) 45*30fdc8d8SChris Lattner { 46*30fdc8d8SChris Lattner 47*30fdc8d8SChris Lattner SetOkayToDiscard (discard_on_error); 48*30fdc8d8SChris Lattner 49*30fdc8d8SChris Lattner Process& process = thread.GetProcess(); 50*30fdc8d8SChris Lattner Target& target = process.GetTarget(); 51*30fdc8d8SChris Lattner const ABI *abi = process.GetABI(); 52*30fdc8d8SChris Lattner 53*30fdc8d8SChris Lattner if (!abi) 54*30fdc8d8SChris Lattner return; 55*30fdc8d8SChris Lattner 56*30fdc8d8SChris Lattner lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 57*30fdc8d8SChris Lattner 58*30fdc8d8SChris Lattner SymbolContextList contexts; 59*30fdc8d8SChris Lattner SymbolContext context; 60*30fdc8d8SChris Lattner ModuleSP executableModuleSP (target.GetExecutableModule()); 61*30fdc8d8SChris Lattner 62*30fdc8d8SChris Lattner if (!executableModuleSP || 63*30fdc8d8SChris Lattner !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 64*30fdc8d8SChris Lattner return; 65*30fdc8d8SChris Lattner 66*30fdc8d8SChris Lattner contexts.GetContextAtIndex(0, context); 67*30fdc8d8SChris Lattner 68*30fdc8d8SChris Lattner m_start_addr = context.symbol->GetValue(); 69*30fdc8d8SChris Lattner lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process); 70*30fdc8d8SChris Lattner 71*30fdc8d8SChris Lattner if (!thread.SaveFrameZeroState(m_register_backup)) 72*30fdc8d8SChris Lattner return; 73*30fdc8d8SChris Lattner 74*30fdc8d8SChris Lattner m_function_addr = function; 75*30fdc8d8SChris Lattner lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process); 76*30fdc8d8SChris Lattner 77*30fdc8d8SChris Lattner if (!abi->PrepareTrivialCall(thread, 78*30fdc8d8SChris Lattner spBelowRedZone, 79*30fdc8d8SChris Lattner FunctionLoadAddr, 80*30fdc8d8SChris Lattner StartLoadAddr, 81*30fdc8d8SChris Lattner m_arg_addr)) 82*30fdc8d8SChris Lattner return; 83*30fdc8d8SChris Lattner 84*30fdc8d8SChris Lattner m_valid = true; 85*30fdc8d8SChris Lattner } 86*30fdc8d8SChris Lattner 87*30fdc8d8SChris Lattner ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread, 88*30fdc8d8SChris Lattner Address &function, 89*30fdc8d8SChris Lattner ValueList &args, 90*30fdc8d8SChris Lattner bool stop_other_threads, 91*30fdc8d8SChris Lattner bool discard_on_error) : 92*30fdc8d8SChris Lattner ThreadPlan ("Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion), 93*30fdc8d8SChris Lattner m_valid(false), 94*30fdc8d8SChris Lattner m_process(thread.GetProcess()), 95*30fdc8d8SChris Lattner m_arg_addr (0), 96*30fdc8d8SChris Lattner m_args (&args), 97*30fdc8d8SChris Lattner m_thread(thread), 98*30fdc8d8SChris Lattner m_stop_other_threads(stop_other_threads) 99*30fdc8d8SChris Lattner { 100*30fdc8d8SChris Lattner 101*30fdc8d8SChris Lattner SetOkayToDiscard (discard_on_error); 102*30fdc8d8SChris Lattner 103*30fdc8d8SChris Lattner Process& process = thread.GetProcess(); 104*30fdc8d8SChris Lattner Target& target = process.GetTarget(); 105*30fdc8d8SChris Lattner const ABI *abi = process.GetABI(); 106*30fdc8d8SChris Lattner 107*30fdc8d8SChris Lattner if(!abi) 108*30fdc8d8SChris Lattner return; 109*30fdc8d8SChris Lattner 110*30fdc8d8SChris Lattner lldb::addr_t spBelowRedZone = thread.GetRegisterContext()->GetSP() - abi->GetRedZoneSize(); 111*30fdc8d8SChris Lattner 112*30fdc8d8SChris Lattner SymbolContextList contexts; 113*30fdc8d8SChris Lattner SymbolContext context; 114*30fdc8d8SChris Lattner ModuleSP executableModuleSP (target.GetExecutableModule()); 115*30fdc8d8SChris Lattner 116*30fdc8d8SChris Lattner if (!executableModuleSP || 117*30fdc8d8SChris Lattner !executableModuleSP->FindSymbolsWithNameAndType(ConstString ("start"), eSymbolTypeCode, contexts)) 118*30fdc8d8SChris Lattner return; 119*30fdc8d8SChris Lattner 120*30fdc8d8SChris Lattner contexts.GetContextAtIndex(0, context); 121*30fdc8d8SChris Lattner 122*30fdc8d8SChris Lattner m_start_addr = context.symbol->GetValue(); 123*30fdc8d8SChris Lattner lldb::addr_t StartLoadAddr = m_start_addr.GetLoadAddress(&process); 124*30fdc8d8SChris Lattner 125*30fdc8d8SChris Lattner if(!thread.SaveFrameZeroState(m_register_backup)) 126*30fdc8d8SChris Lattner return; 127*30fdc8d8SChris Lattner 128*30fdc8d8SChris Lattner m_function_addr = function; 129*30fdc8d8SChris Lattner lldb::addr_t FunctionLoadAddr = m_function_addr.GetLoadAddress(&process); 130*30fdc8d8SChris Lattner 131*30fdc8d8SChris Lattner if (!abi->PrepareNormalCall(thread, 132*30fdc8d8SChris Lattner spBelowRedZone, 133*30fdc8d8SChris Lattner FunctionLoadAddr, 134*30fdc8d8SChris Lattner StartLoadAddr, 135*30fdc8d8SChris Lattner *m_args)) 136*30fdc8d8SChris Lattner return; 137*30fdc8d8SChris Lattner 138*30fdc8d8SChris Lattner m_valid = true; 139*30fdc8d8SChris Lattner } 140*30fdc8d8SChris Lattner 141*30fdc8d8SChris Lattner ThreadPlanCallFunction::~ThreadPlanCallFunction () 142*30fdc8d8SChris Lattner { 143*30fdc8d8SChris Lattner } 144*30fdc8d8SChris Lattner 145*30fdc8d8SChris Lattner void 146*30fdc8d8SChris Lattner ThreadPlanCallFunction::GetDescription (Stream *s, lldb::DescriptionLevel level) 147*30fdc8d8SChris Lattner { 148*30fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 149*30fdc8d8SChris Lattner { 150*30fdc8d8SChris Lattner s->Printf("Function call thread plan"); 151*30fdc8d8SChris Lattner } 152*30fdc8d8SChris Lattner else 153*30fdc8d8SChris Lattner { 154*30fdc8d8SChris Lattner if (m_args) 155*30fdc8d8SChris Lattner s->Printf("Thread plan to call 0x%llx with parsed arguments", m_function_addr.GetLoadAddress(&m_process), m_arg_addr); 156*30fdc8d8SChris Lattner else 157*30fdc8d8SChris Lattner s->Printf("Thread plan to call 0x%llx void * argument at: 0x%llx", m_function_addr.GetLoadAddress(&m_process), m_arg_addr); 158*30fdc8d8SChris Lattner } 159*30fdc8d8SChris Lattner } 160*30fdc8d8SChris Lattner 161*30fdc8d8SChris Lattner bool 162*30fdc8d8SChris Lattner ThreadPlanCallFunction::ValidatePlan (Stream *error) 163*30fdc8d8SChris Lattner { 164*30fdc8d8SChris Lattner if (!m_valid) 165*30fdc8d8SChris Lattner return false; 166*30fdc8d8SChris Lattner 167*30fdc8d8SChris Lattner return true; 168*30fdc8d8SChris Lattner } 169*30fdc8d8SChris Lattner 170*30fdc8d8SChris Lattner bool 171*30fdc8d8SChris Lattner ThreadPlanCallFunction::PlanExplainsStop () 172*30fdc8d8SChris Lattner { 173*30fdc8d8SChris Lattner if (!m_subplan_sp) 174*30fdc8d8SChris Lattner return false; 175*30fdc8d8SChris Lattner else 176*30fdc8d8SChris Lattner return m_subplan_sp->PlanExplainsStop(); 177*30fdc8d8SChris Lattner } 178*30fdc8d8SChris Lattner 179*30fdc8d8SChris Lattner bool 180*30fdc8d8SChris Lattner ThreadPlanCallFunction::ShouldStop (Event *event_ptr) 181*30fdc8d8SChris Lattner { 182*30fdc8d8SChris Lattner if (PlanExplainsStop()) 183*30fdc8d8SChris Lattner { 184*30fdc8d8SChris Lattner m_thread.RestoreSaveFrameZero(m_register_backup); 185*30fdc8d8SChris Lattner m_thread.ClearStackFrames(); 186*30fdc8d8SChris Lattner SetPlanComplete(); 187*30fdc8d8SChris Lattner return true; 188*30fdc8d8SChris Lattner } 189*30fdc8d8SChris Lattner else 190*30fdc8d8SChris Lattner { 191*30fdc8d8SChris Lattner return false; 192*30fdc8d8SChris Lattner } 193*30fdc8d8SChris Lattner } 194*30fdc8d8SChris Lattner 195*30fdc8d8SChris Lattner bool 196*30fdc8d8SChris Lattner ThreadPlanCallFunction::StopOthers () 197*30fdc8d8SChris Lattner { 198*30fdc8d8SChris Lattner return m_stop_other_threads; 199*30fdc8d8SChris Lattner } 200*30fdc8d8SChris Lattner 201*30fdc8d8SChris Lattner void 202*30fdc8d8SChris Lattner ThreadPlanCallFunction::SetStopOthers (bool new_value) 203*30fdc8d8SChris Lattner { 204*30fdc8d8SChris Lattner if (m_subplan_sp) 205*30fdc8d8SChris Lattner { 206*30fdc8d8SChris Lattner ThreadPlanRunToAddress *address_plan = static_cast<ThreadPlanRunToAddress *>(m_subplan_sp.get()); 207*30fdc8d8SChris Lattner address_plan->SetStopOthers(new_value); 208*30fdc8d8SChris Lattner } 209*30fdc8d8SChris Lattner m_stop_other_threads = new_value; 210*30fdc8d8SChris Lattner } 211*30fdc8d8SChris Lattner 212*30fdc8d8SChris Lattner StateType 213*30fdc8d8SChris Lattner ThreadPlanCallFunction::RunState () 214*30fdc8d8SChris Lattner { 215*30fdc8d8SChris Lattner return eStateRunning; 216*30fdc8d8SChris Lattner } 217*30fdc8d8SChris Lattner 218*30fdc8d8SChris Lattner void 219*30fdc8d8SChris Lattner ThreadPlanCallFunction::DidPush () 220*30fdc8d8SChris Lattner { 221*30fdc8d8SChris Lattner m_subplan_sp.reset(new ThreadPlanRunToAddress(m_thread, m_start_addr, m_stop_other_threads)); 222*30fdc8d8SChris Lattner 223*30fdc8d8SChris Lattner m_thread.QueueThreadPlan(m_subplan_sp, false); 224*30fdc8d8SChris Lattner 225*30fdc8d8SChris Lattner } 226*30fdc8d8SChris Lattner 227*30fdc8d8SChris Lattner bool 228*30fdc8d8SChris Lattner ThreadPlanCallFunction::WillStop () 229*30fdc8d8SChris Lattner { 230*30fdc8d8SChris Lattner return true; 231*30fdc8d8SChris Lattner } 232*30fdc8d8SChris Lattner 233*30fdc8d8SChris Lattner bool 234*30fdc8d8SChris Lattner ThreadPlanCallFunction::MischiefManaged () 235*30fdc8d8SChris Lattner { 236*30fdc8d8SChris Lattner if (IsPlanComplete()) 237*30fdc8d8SChris Lattner { 238*30fdc8d8SChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 239*30fdc8d8SChris Lattner 240*30fdc8d8SChris Lattner if (log) 241*30fdc8d8SChris Lattner log->Printf("Completed call function plan."); 242*30fdc8d8SChris Lattner 243*30fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 244*30fdc8d8SChris Lattner return true; 245*30fdc8d8SChris Lattner } 246*30fdc8d8SChris Lattner else 247*30fdc8d8SChris Lattner { 248*30fdc8d8SChris Lattner return false; 249*30fdc8d8SChris Lattner } 250*30fdc8d8SChris Lattner } 251