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 10e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanRunToAddress.h" 1130fdc8d8SChris Lattner #include "lldb/Target/Process.h" 1230fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h" 13b9c1b51eSKate Stone #include "lldb/Target/Target.h" 14b9c1b51eSKate Stone #include "lldb/Target/Thread.h" 156f9e6901SZachary Turner #include "lldb/Utility/Log.h" 16bf9a7730SZachary Turner #include "lldb/Utility/Stream.h" 1730fdc8d8SChris Lattner 1830fdc8d8SChris Lattner using namespace lldb; 1930fdc8d8SChris Lattner using namespace lldb_private; 2030fdc8d8SChris Lattner 2130fdc8d8SChris Lattner //---------------------------------------------------------------------- 2230fdc8d8SChris Lattner // ThreadPlanRunToAddress: Continue plan 2330fdc8d8SChris Lattner //---------------------------------------------------------------------- 2430fdc8d8SChris Lattner 25b9c1b51eSKate Stone ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address, 26b9c1b51eSKate Stone bool stop_others) 27b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 28b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion), 29b9c1b51eSKate Stone m_stop_others(stop_others), m_addresses(), m_break_ids() { 30b9c1b51eSKate Stone m_addresses.push_back( 31b9c1b51eSKate Stone address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get())); 3208b87e0dSJim Ingham SetInitialBreakpoints(); 3330fdc8d8SChris Lattner } 3430fdc8d8SChris Lattner 35b9c1b51eSKate Stone ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, 3630fdc8d8SChris Lattner lldb::addr_t address, 37b9c1b51eSKate Stone bool stop_others) 38b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 39b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion), 40b9c1b51eSKate Stone m_stop_others(stop_others), m_addresses(), m_break_ids() { 41b9c1b51eSKate Stone m_addresses.push_back( 42b9c1b51eSKate Stone m_thread.CalculateTarget()->GetOpcodeLoadAddress(address)); 4308b87e0dSJim Ingham SetInitialBreakpoints(); 4408b87e0dSJim Ingham } 4508b87e0dSJim Ingham 46b9c1b51eSKate Stone ThreadPlanRunToAddress::ThreadPlanRunToAddress( 47b9c1b51eSKate Stone Thread &thread, const std::vector<lldb::addr_t> &addresses, 48b9c1b51eSKate Stone bool stop_others) 49b9c1b51eSKate Stone : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread, 50b9c1b51eSKate Stone eVoteNoOpinion, eVoteNoOpinion), 51b9c1b51eSKate Stone m_stop_others(stop_others), m_addresses(addresses), m_break_ids() { 52d93c4a33SBruce Mitchener // Convert all addresses into opcode addresses to make sure we set 53f3ef3d2aSGreg Clayton // breakpoints at the correct address. 541ac04c30SGreg Clayton Target &target = thread.GetProcess()->GetTarget(); 55f3ef3d2aSGreg Clayton std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end(); 56f3ef3d2aSGreg Clayton for (pos = m_addresses.begin(); pos != end; ++pos) 57f3ef3d2aSGreg Clayton *pos = target.GetOpcodeLoadAddress(*pos); 58f3ef3d2aSGreg Clayton 5908b87e0dSJim Ingham SetInitialBreakpoints(); 6030fdc8d8SChris Lattner } 6130fdc8d8SChris Lattner 62b9c1b51eSKate Stone void ThreadPlanRunToAddress::SetInitialBreakpoints() { 6308b87e0dSJim Ingham size_t num_addresses = m_addresses.size(); 6408b87e0dSJim Ingham m_break_ids.resize(num_addresses); 6508b87e0dSJim Ingham 66b9c1b51eSKate Stone for (size_t i = 0; i < num_addresses; i++) { 6730fdc8d8SChris Lattner Breakpoint *breakpoint; 68b9c1b51eSKate Stone breakpoint = m_thread.CalculateTarget() 69b9c1b51eSKate Stone ->CreateBreakpoint(m_addresses[i], true, false) 70b9c1b51eSKate Stone .get(); 71b9c1b51eSKate Stone if (breakpoint != nullptr) { 72*e103ae92SJonas Devlieghere if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations()) 73*e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = true; 7408b87e0dSJim Ingham m_break_ids[i] = breakpoint->GetID(); 7530fdc8d8SChris Lattner breakpoint->SetThreadID(m_thread.GetID()); 762995077dSJim Ingham breakpoint->SetBreakpointKind("run-to-address"); 7730fdc8d8SChris Lattner } 7830fdc8d8SChris Lattner } 7908b87e0dSJim Ingham } 8030fdc8d8SChris Lattner 81b9c1b51eSKate Stone ThreadPlanRunToAddress::~ThreadPlanRunToAddress() { 8208b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 83b9c1b51eSKate Stone for (size_t i = 0; i < num_break_ids; i++) { 841ac04c30SGreg Clayton m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 8530fdc8d8SChris Lattner } 86*e103ae92SJonas Devlieghere m_could_not_resolve_hw_bp = false; 8730fdc8d8SChris Lattner } 8830fdc8d8SChris Lattner 89b9c1b51eSKate Stone void ThreadPlanRunToAddress::GetDescription(Stream *s, 90b9c1b51eSKate Stone lldb::DescriptionLevel level) { 9108b87e0dSJim Ingham size_t num_addresses = m_addresses.size(); 9208b87e0dSJim Ingham 93b9c1b51eSKate Stone if (level == lldb::eDescriptionLevelBrief) { 94b9c1b51eSKate Stone if (num_addresses == 0) { 9508b87e0dSJim Ingham s->Printf("run to address with no addresses given."); 9608b87e0dSJim Ingham return; 97b9c1b51eSKate Stone } else if (num_addresses == 1) 9830fdc8d8SChris Lattner s->Printf("run to address: "); 9908b87e0dSJim Ingham else 10008b87e0dSJim Ingham s->Printf("run to addresses: "); 10108b87e0dSJim Ingham 102b9c1b51eSKate Stone for (size_t i = 0; i < num_addresses; i++) { 10308b87e0dSJim Ingham s->Address(m_addresses[i], sizeof(addr_t)); 10408b87e0dSJim Ingham s->Printf(" "); 10508b87e0dSJim Ingham } 106b9c1b51eSKate Stone } else { 107b9c1b51eSKate Stone if (num_addresses == 0) { 10808b87e0dSJim Ingham s->Printf("run to address with no addresses given."); 10908b87e0dSJim Ingham return; 110b9c1b51eSKate Stone } else if (num_addresses == 1) 11130fdc8d8SChris Lattner s->Printf("Run to address: "); 112b9c1b51eSKate Stone else { 11308b87e0dSJim Ingham s->Printf("Run to addresses: "); 11408b87e0dSJim Ingham } 11508b87e0dSJim Ingham 116b9c1b51eSKate Stone for (size_t i = 0; i < num_addresses; i++) { 117b9c1b51eSKate Stone if (num_addresses > 1) { 11808b87e0dSJim Ingham s->Printf("\n"); 11908b87e0dSJim Ingham s->Indent(); 12008b87e0dSJim Ingham } 12108b87e0dSJim Ingham 12208b87e0dSJim Ingham s->Address(m_addresses[i], sizeof(addr_t)); 123f58a0487SJim Ingham s->Printf(" using breakpoint: %d - ", m_break_ids[i]); 124b9c1b51eSKate Stone Breakpoint *breakpoint = 125b9c1b51eSKate Stone m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get(); 12630fdc8d8SChris Lattner if (breakpoint) 12730fdc8d8SChris Lattner breakpoint->Dump(s); 12830fdc8d8SChris Lattner else 12930fdc8d8SChris Lattner s->Printf("but the breakpoint has been deleted."); 13030fdc8d8SChris Lattner } 13130fdc8d8SChris Lattner } 13208b87e0dSJim Ingham } 13330fdc8d8SChris Lattner 134b9c1b51eSKate Stone bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) { 135*e103ae92SJonas Devlieghere if (m_could_not_resolve_hw_bp) { 136*e103ae92SJonas Devlieghere if (error) 137*e103ae92SJonas Devlieghere error->Printf("Could not set hardware breakpoint(s)"); 138*e103ae92SJonas Devlieghere return false; 139*e103ae92SJonas Devlieghere } 140*e103ae92SJonas Devlieghere 14105097246SAdrian Prantl // If we couldn't set the breakpoint for some reason, then this won't work. 14208b87e0dSJim Ingham bool all_bps_good = true; 14308b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 144b9c1b51eSKate Stone for (size_t i = 0; i < num_break_ids; i++) { 145b9c1b51eSKate Stone if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) { 14608b87e0dSJim Ingham all_bps_good = false; 147b9c1b51eSKate Stone if (error) { 14808b87e0dSJim Ingham error->Printf("Could not set breakpoint for address: "); 14908b87e0dSJim Ingham error->Address(m_addresses[i], sizeof(addr_t)); 15008b87e0dSJim Ingham error->Printf("\n"); 15108b87e0dSJim Ingham } 15208b87e0dSJim Ingham } 153f48169bbSJim Ingham } 15408b87e0dSJim Ingham return all_bps_good; 15530fdc8d8SChris Lattner } 15630fdc8d8SChris Lattner 157b9c1b51eSKate Stone bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) { 15830fdc8d8SChris Lattner return AtOurAddress(); 15930fdc8d8SChris Lattner } 16030fdc8d8SChris Lattner 161b9c1b51eSKate Stone bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) { 1621fd2f08eSJim Ingham return AtOurAddress(); 16330fdc8d8SChris Lattner } 16430fdc8d8SChris Lattner 165b9c1b51eSKate Stone bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; } 16630fdc8d8SChris Lattner 167b9c1b51eSKate Stone void ThreadPlanRunToAddress::SetStopOthers(bool new_value) { 16830fdc8d8SChris Lattner m_stop_others = new_value; 16930fdc8d8SChris Lattner } 17030fdc8d8SChris Lattner 171b9c1b51eSKate Stone StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; } 17230fdc8d8SChris Lattner 173b9c1b51eSKate Stone bool ThreadPlanRunToAddress::WillStop() { return true; } 17430fdc8d8SChris Lattner 175b9c1b51eSKate Stone bool ThreadPlanRunToAddress::MischiefManaged() { 1765160ce5cSGreg Clayton Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); 17730fdc8d8SChris Lattner 178b9c1b51eSKate Stone if (AtOurAddress()) { 17930fdc8d8SChris Lattner // Remove the breakpoint 18008b87e0dSJim Ingham size_t num_break_ids = m_break_ids.size(); 18130fdc8d8SChris Lattner 182b9c1b51eSKate Stone for (size_t i = 0; i < num_break_ids; i++) { 183b9c1b51eSKate Stone if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) { 1841ac04c30SGreg Clayton m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]); 18508b87e0dSJim Ingham m_break_ids[i] = LLDB_INVALID_BREAK_ID; 18608b87e0dSJim Ingham } 18708b87e0dSJim Ingham } 18830fdc8d8SChris Lattner if (log) 18930fdc8d8SChris Lattner log->Printf("Completed run to address plan."); 19030fdc8d8SChris Lattner ThreadPlan::MischiefManaged(); 19130fdc8d8SChris Lattner return true; 192b9c1b51eSKate Stone } else 19330fdc8d8SChris Lattner return false; 19430fdc8d8SChris Lattner } 19530fdc8d8SChris Lattner 196b9c1b51eSKate Stone bool ThreadPlanRunToAddress::AtOurAddress() { 19730fdc8d8SChris Lattner lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC(); 19808b87e0dSJim Ingham bool found_it = false; 1994bf570d6SJim Ingham size_t num_addresses = m_addresses.size(); 200b9c1b51eSKate Stone for (size_t i = 0; i < num_addresses; i++) { 201b9c1b51eSKate Stone if (m_addresses[i] == current_address) { 20208b87e0dSJim Ingham found_it = true; 20308b87e0dSJim Ingham break; 20408b87e0dSJim Ingham } 20508b87e0dSJim Ingham } 20608b87e0dSJim Ingham return found_it; 20730fdc8d8SChris Lattner } 208