130fdc8d8SChris Lattner //===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===// 230fdc8d8SChris Lattner // 330fdc8d8SChris Lattner // The LLVM Compiler Infrastructure 430fdc8d8SChris Lattner // 530fdc8d8SChris Lattner // This file is distributed under the University of Illinois Open Source 630fdc8d8SChris Lattner // License. See LICENSE.TXT for details. 730fdc8d8SChris Lattner // 830fdc8d8SChris Lattner //===----------------------------------------------------------------------===// 930fdc8d8SChris Lattner 1030fdc8d8SChris Lattner #include "lldb/Target/ThreadPlanRunToAddress.h" 1130fdc8d8SChris Lattner 1230fdc8d8SChris Lattner // C Includes 1330fdc8d8SChris Lattner // C++ Includes 1430fdc8d8SChris Lattner // Other libraries and framework includes 1530fdc8d8SChris Lattner // Project includes 1630fdc8d8SChris Lattner #include "lldb/lldb-private-log.h" 1730fdc8d8SChris Lattner #include "lldb/Core/Log.h" 1830fdc8d8SChris Lattner #include "lldb/Core/Stream.h" 1930fdc8d8SChris Lattner #include "lldb/Target/Target.h" 2030fdc8d8SChris Lattner #include "lldb/Target/Process.h" 2130fdc8d8SChris Lattner #include "lldb/Target/Thread.h" 2230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 2330fdc8d8SChris Lattner 2430fdc8d8SChris Lattner using namespace lldb; 2530fdc8d8SChris Lattner using namespace lldb_private; 2630fdc8d8SChris Lattner 2730fdc8d8SChris Lattner //---------------------------------------------------------------------- 2830fdc8d8SChris Lattner // ThreadPlanRunToAddress: Continue plan 2930fdc8d8SChris Lattner //---------------------------------------------------------------------- 3030fdc8d8SChris Lattner 3130fdc8d8SChris Lattner ThreadPlanRunToAddress::ThreadPlanRunToAddress 3230fdc8d8SChris Lattner ( 3330fdc8d8SChris Lattner Thread &thread, 3430fdc8d8SChris Lattner Address &address, 3530fdc8d8SChris Lattner bool stop_others 3630fdc8d8SChris Lattner ) : 3708b87e0dSJim Ingham ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 3830fdc8d8SChris Lattner m_stop_others (stop_others), 3908b87e0dSJim Ingham m_addresses (), 4008b87e0dSJim Ingham m_break_ids () 4130fdc8d8SChris Lattner { 421ac04c30SGreg Clayton m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get())); 4308b87e0dSJim Ingham SetInitialBreakpoints(); 4430fdc8d8SChris Lattner } 4530fdc8d8SChris Lattner 4630fdc8d8SChris Lattner ThreadPlanRunToAddress::ThreadPlanRunToAddress 4730fdc8d8SChris Lattner ( 4830fdc8d8SChris Lattner Thread &thread, 4930fdc8d8SChris Lattner lldb::addr_t address, 5030fdc8d8SChris Lattner bool stop_others 5130fdc8d8SChris Lattner ) : 5208b87e0dSJim Ingham ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 5330fdc8d8SChris Lattner m_stop_others (stop_others), 5408b87e0dSJim Ingham m_addresses (), 5508b87e0dSJim Ingham m_break_ids () 5630fdc8d8SChris Lattner { 571ac04c30SGreg Clayton m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 5808b87e0dSJim Ingham SetInitialBreakpoints(); 5908b87e0dSJim Ingham } 6008b87e0dSJim Ingham 6108b87e0dSJim Ingham ThreadPlanRunToAddress::ThreadPlanRunToAddress 6208b87e0dSJim Ingham ( 6308b87e0dSJim Ingham Thread &thread, 64f3ef3d2aSGreg Clayton const std::vector<lldb::addr_t> &addresses, 6508b87e0dSJim Ingham bool stop_others 6608b87e0dSJim Ingham ) : 6708b87e0dSJim Ingham ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion), 6808b87e0dSJim Ingham m_stop_others (stop_others), 6908b87e0dSJim Ingham m_addresses (addresses), 7008b87e0dSJim Ingham m_break_ids () 7108b87e0dSJim Ingham { 72f3ef3d2aSGreg Clayton // Convert all addressses into opcode addresses to make sure we set 73f3ef3d2aSGreg Clayton // breakpoints at the correct address. 741ac04c30SGreg Clayton Target &target = thread.GetProcess()->GetTarget(); 75f3ef3d2aSGreg Clayton std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end(); 76f3ef3d2aSGreg Clayton for (pos = m_addresses.begin(); pos != end; ++pos) 77f3ef3d2aSGreg Clayton *pos = target.GetOpcodeLoadAddress (*pos); 78f3ef3d2aSGreg Clayton 7908b87e0dSJim Ingham SetInitialBreakpoints(); 8030fdc8d8SChris Lattner } 8130fdc8d8SChris Lattner 8230fdc8d8SChris Lattner void 8308b87e0dSJim Ingham ThreadPlanRunToAddress::SetInitialBreakpoints () 8408b87e0dSJim Ingham { 8508b87e0dSJim Ingham size_t num_addresses = m_addresses.size(); 8608b87e0dSJim Ingham m_break_ids.resize(num_addresses); 8708b87e0dSJim Ingham 8808b87e0dSJim Ingham for (size_t i = 0; i < num_addresses; i++) 8930fdc8d8SChris Lattner { 9030fdc8d8SChris Lattner Breakpoint *breakpoint; 911ac04c30SGreg Clayton breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true).get(); 9230fdc8d8SChris Lattner if (breakpoint != NULL) 9330fdc8d8SChris Lattner { 9408b87e0dSJim Ingham m_break_ids[i] = breakpoint->GetID(); 9530fdc8d8SChris Lattner breakpoint->SetThreadID(m_thread.GetID()); 962995077dSJim Ingham breakpoint->SetBreakpointKind("run-to-address"); 9730fdc8d8SChris Lattner } 9830fdc8d8SChris Lattner } 9908b87e0dSJim Ingham } 10030fdc8d8SChris Lattner 10130fdc8d8SChris Lattner ThreadPlanRunToAddress::~ThreadPlanRunToAddress () 10230fdc8d8SChris Lattner { 10308b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 10408b87e0dSJim Ingham for (size_t i = 0; i < num_break_ids; i++) 10530fdc8d8SChris Lattner { 1061ac04c30SGreg Clayton m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]); 10730fdc8d8SChris Lattner } 10830fdc8d8SChris Lattner } 10930fdc8d8SChris Lattner 11030fdc8d8SChris Lattner void 11130fdc8d8SChris Lattner ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level) 11230fdc8d8SChris Lattner { 11308b87e0dSJim Ingham size_t num_addresses = m_addresses.size(); 11408b87e0dSJim Ingham 11530fdc8d8SChris Lattner if (level == lldb::eDescriptionLevelBrief) 11630fdc8d8SChris Lattner { 11708b87e0dSJim Ingham if (num_addresses == 0) 11808b87e0dSJim Ingham { 11908b87e0dSJim Ingham s->Printf ("run to address with no addresses given."); 12008b87e0dSJim Ingham return; 12108b87e0dSJim Ingham } 12208b87e0dSJim Ingham else if (num_addresses == 1) 12330fdc8d8SChris Lattner s->Printf ("run to address: "); 12408b87e0dSJim Ingham else 12508b87e0dSJim Ingham s->Printf ("run to addresses: "); 12608b87e0dSJim Ingham 12708b87e0dSJim Ingham for (size_t i = 0; i < num_addresses; i++) 12808b87e0dSJim Ingham { 12908b87e0dSJim Ingham s->Address (m_addresses[i], sizeof (addr_t)); 13008b87e0dSJim Ingham s->Printf(" "); 13108b87e0dSJim Ingham } 13230fdc8d8SChris Lattner } 13330fdc8d8SChris Lattner else 13430fdc8d8SChris Lattner { 13508b87e0dSJim Ingham if (num_addresses == 0) 13608b87e0dSJim Ingham { 13708b87e0dSJim Ingham s->Printf ("run to address with no addresses given."); 13808b87e0dSJim Ingham return; 13908b87e0dSJim Ingham } 14008b87e0dSJim Ingham else if (num_addresses == 1) 14130fdc8d8SChris Lattner s->Printf ("Run to address: "); 14208b87e0dSJim Ingham else 14308b87e0dSJim Ingham { 14408b87e0dSJim Ingham s->Printf ("Run to addresses: "); 14508b87e0dSJim Ingham } 14608b87e0dSJim Ingham 14708b87e0dSJim Ingham for (size_t i = 0; i < num_addresses; i++) 14808b87e0dSJim Ingham { 14908b87e0dSJim Ingham if (num_addresses > 1) 15008b87e0dSJim Ingham { 15108b87e0dSJim Ingham s->Printf("\n"); 15208b87e0dSJim Ingham s->Indent(); 15308b87e0dSJim Ingham } 15408b87e0dSJim Ingham 15508b87e0dSJim Ingham s->Address(m_addresses[i], sizeof (addr_t)); 156f58a0487SJim Ingham s->Printf (" using breakpoint: %d - ", m_break_ids[i]); 1571ac04c30SGreg Clayton Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get(); 15830fdc8d8SChris Lattner if (breakpoint) 15930fdc8d8SChris Lattner breakpoint->Dump (s); 16030fdc8d8SChris Lattner else 16130fdc8d8SChris Lattner s->Printf ("but the breakpoint has been deleted."); 16230fdc8d8SChris Lattner } 16330fdc8d8SChris Lattner } 16408b87e0dSJim Ingham } 16530fdc8d8SChris Lattner 16630fdc8d8SChris Lattner bool 16730fdc8d8SChris Lattner ThreadPlanRunToAddress::ValidatePlan (Stream *error) 16830fdc8d8SChris Lattner { 16930fdc8d8SChris Lattner // If we couldn't set the breakpoint for some reason, then this won't 17030fdc8d8SChris Lattner // work. 17108b87e0dSJim Ingham bool all_bps_good = true; 17208b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 17308b87e0dSJim Ingham 17408b87e0dSJim Ingham for (size_t i = 0; i < num_break_ids; i++) 17508b87e0dSJim Ingham { 17608b87e0dSJim Ingham if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) 17708b87e0dSJim Ingham { 17808b87e0dSJim Ingham all_bps_good = false; 179f48169bbSJim Ingham if (error) 180f48169bbSJim Ingham { 18108b87e0dSJim Ingham error->Printf ("Could not set breakpoint for address: "); 18208b87e0dSJim Ingham error->Address (m_addresses[i], sizeof (addr_t)); 18308b87e0dSJim Ingham error->Printf ("\n"); 18408b87e0dSJim Ingham } 18508b87e0dSJim Ingham } 186f48169bbSJim Ingham } 18708b87e0dSJim Ingham return all_bps_good; 18830fdc8d8SChris Lattner } 18930fdc8d8SChris Lattner 19030fdc8d8SChris Lattner bool 191*221d51cfSJim Ingham ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr) 19230fdc8d8SChris Lattner { 19330fdc8d8SChris Lattner return AtOurAddress(); 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner 19630fdc8d8SChris Lattner bool 19730fdc8d8SChris Lattner ThreadPlanRunToAddress::ShouldStop (Event *event_ptr) 19830fdc8d8SChris Lattner { 19930fdc8d8SChris Lattner return false; 20030fdc8d8SChris Lattner } 20130fdc8d8SChris Lattner 20230fdc8d8SChris Lattner bool 20330fdc8d8SChris Lattner ThreadPlanRunToAddress::StopOthers () 20430fdc8d8SChris Lattner { 20530fdc8d8SChris Lattner return m_stop_others; 20630fdc8d8SChris Lattner } 20730fdc8d8SChris Lattner 20830fdc8d8SChris Lattner void 20930fdc8d8SChris Lattner ThreadPlanRunToAddress::SetStopOthers (bool new_value) 21030fdc8d8SChris Lattner { 21130fdc8d8SChris Lattner m_stop_others = new_value; 21230fdc8d8SChris Lattner } 21330fdc8d8SChris Lattner 21430fdc8d8SChris Lattner StateType 21506e827ccSJim Ingham ThreadPlanRunToAddress::GetPlanRunState () 21630fdc8d8SChris Lattner { 21730fdc8d8SChris Lattner return eStateRunning; 21830fdc8d8SChris Lattner } 21930fdc8d8SChris Lattner 22030fdc8d8SChris Lattner bool 22130fdc8d8SChris Lattner ThreadPlanRunToAddress::WillStop () 22230fdc8d8SChris Lattner { 22330fdc8d8SChris Lattner return true; 22430fdc8d8SChris Lattner } 22530fdc8d8SChris Lattner 22630fdc8d8SChris Lattner bool 22730fdc8d8SChris Lattner ThreadPlanRunToAddress::MischiefManaged () 22830fdc8d8SChris Lattner { 2295160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); 23030fdc8d8SChris Lattner 23130fdc8d8SChris Lattner if (AtOurAddress()) 23230fdc8d8SChris Lattner { 23330fdc8d8SChris Lattner // Remove the breakpoint 23408b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 23530fdc8d8SChris Lattner 23608b87e0dSJim Ingham for (size_t i = 0; i < num_break_ids; i++) 23708b87e0dSJim Ingham { 23808b87e0dSJim Ingham if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) 23908b87e0dSJim Ingham { 2401ac04c30SGreg Clayton m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]); 24108b87e0dSJim Ingham m_break_ids[i] = LLDB_INVALID_BREAK_ID; 24208b87e0dSJim Ingham } 24308b87e0dSJim Ingham } 24430fdc8d8SChris Lattner if (log) 24530fdc8d8SChris Lattner log->Printf("Completed run to address plan."); 24630fdc8d8SChris Lattner ThreadPlan::MischiefManaged (); 24730fdc8d8SChris Lattner return true; 24830fdc8d8SChris Lattner } 24930fdc8d8SChris Lattner else 25030fdc8d8SChris Lattner return false; 25130fdc8d8SChris Lattner } 25230fdc8d8SChris Lattner 25330fdc8d8SChris Lattner bool 25430fdc8d8SChris Lattner ThreadPlanRunToAddress::AtOurAddress () 25530fdc8d8SChris Lattner { 25630fdc8d8SChris Lattner lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC(); 25708b87e0dSJim Ingham bool found_it = false; 2584bf570d6SJim Ingham size_t num_addresses = m_addresses.size(); 2594bf570d6SJim Ingham for (size_t i = 0; i < num_addresses; i++) 26008b87e0dSJim Ingham { 26108b87e0dSJim Ingham if (m_addresses[i] == current_address) 26208b87e0dSJim Ingham { 26308b87e0dSJim Ingham found_it = true; 26408b87e0dSJim Ingham break; 26508b87e0dSJim Ingham } 26608b87e0dSJim Ingham } 26708b87e0dSJim Ingham return found_it; 26830fdc8d8SChris Lattner } 269