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 {
42*f3ef3d2aSGreg Clayton     m_addresses.push_back (address.GetOpcodeLoadAddress (&m_thread.GetProcess().GetTarget()));
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 {
57*f3ef3d2aSGreg Clayton     m_addresses.push_back(m_thread.GetProcess().GetTarget().GetOpcodeLoadAddress(address));
5808b87e0dSJim Ingham     SetInitialBreakpoints();
5908b87e0dSJim Ingham }
6008b87e0dSJim Ingham 
6108b87e0dSJim Ingham ThreadPlanRunToAddress::ThreadPlanRunToAddress
6208b87e0dSJim Ingham (
6308b87e0dSJim Ingham     Thread &thread,
64*f3ef3d2aSGreg 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 {
72*f3ef3d2aSGreg Clayton     // Convert all addressses into opcode addresses to make sure we set
73*f3ef3d2aSGreg Clayton     // breakpoints at the correct address.
74*f3ef3d2aSGreg Clayton     Target &target = thread.GetProcess().GetTarget();
75*f3ef3d2aSGreg Clayton     std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
76*f3ef3d2aSGreg Clayton     for (pos = m_addresses.begin(); pos != end; ++pos)
77*f3ef3d2aSGreg Clayton         *pos = target.GetOpcodeLoadAddress (*pos);
78*f3ef3d2aSGreg 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;
9108b87e0dSJim Ingham         breakpoint = m_thread.GetProcess().GetTarget().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());
9630fdc8d8SChris Lattner         }
9730fdc8d8SChris Lattner     }
9808b87e0dSJim Ingham }
9930fdc8d8SChris Lattner 
10030fdc8d8SChris Lattner ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
10130fdc8d8SChris Lattner {
10208b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
10308b87e0dSJim Ingham     for (size_t i = 0; i <  num_break_ids; i++)
10430fdc8d8SChris Lattner     {
10508b87e0dSJim Ingham         m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
10630fdc8d8SChris Lattner     }
10730fdc8d8SChris Lattner }
10830fdc8d8SChris Lattner 
10930fdc8d8SChris Lattner void
11030fdc8d8SChris Lattner ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
11130fdc8d8SChris Lattner {
11208b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
11308b87e0dSJim Ingham 
11430fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
11530fdc8d8SChris Lattner     {
11608b87e0dSJim Ingham         if (num_addresses == 0)
11708b87e0dSJim Ingham         {
11808b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
11908b87e0dSJim Ingham             return;
12008b87e0dSJim Ingham         }
12108b87e0dSJim Ingham         else if (num_addresses == 1)
12230fdc8d8SChris Lattner             s->Printf ("run to address: ");
12308b87e0dSJim Ingham         else
12408b87e0dSJim Ingham             s->Printf ("run to addresses: ");
12508b87e0dSJim Ingham 
12608b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
12708b87e0dSJim Ingham         {
12808b87e0dSJim Ingham             s->Address (m_addresses[i], sizeof (addr_t));
12908b87e0dSJim Ingham             s->Printf(" ");
13008b87e0dSJim Ingham         }
13130fdc8d8SChris Lattner     }
13230fdc8d8SChris Lattner     else
13330fdc8d8SChris Lattner     {
13408b87e0dSJim Ingham         if (num_addresses == 0)
13508b87e0dSJim Ingham         {
13608b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
13708b87e0dSJim Ingham             return;
13808b87e0dSJim Ingham         }
13908b87e0dSJim Ingham         else if (num_addresses == 1)
14030fdc8d8SChris Lattner             s->Printf ("Run to address: ");
14108b87e0dSJim Ingham         else
14208b87e0dSJim Ingham         {
14308b87e0dSJim Ingham             s->Printf ("Run to addresses: ");
14408b87e0dSJim Ingham         }
14508b87e0dSJim Ingham 
14608b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
14708b87e0dSJim Ingham         {
14808b87e0dSJim Ingham             if (num_addresses > 1)
14908b87e0dSJim Ingham             {
15008b87e0dSJim Ingham                 s->Printf("\n");
15108b87e0dSJim Ingham                 s->Indent();
15208b87e0dSJim Ingham             }
15308b87e0dSJim Ingham 
15408b87e0dSJim Ingham             s->Address(m_addresses[i], sizeof (addr_t));
15508b87e0dSJim Ingham             s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
15608b87e0dSJim Ingham             Breakpoint *breakpoint = m_thread.GetProcess().GetTarget().GetBreakpointByID (m_break_ids[i]).get();
15730fdc8d8SChris Lattner             if (breakpoint)
15830fdc8d8SChris Lattner                 breakpoint->Dump (s);
15930fdc8d8SChris Lattner             else
16030fdc8d8SChris Lattner                 s->Printf ("but the breakpoint has been deleted.");
16130fdc8d8SChris Lattner         }
16230fdc8d8SChris Lattner     }
16308b87e0dSJim Ingham }
16430fdc8d8SChris Lattner 
16530fdc8d8SChris Lattner bool
16630fdc8d8SChris Lattner ThreadPlanRunToAddress::ValidatePlan (Stream *error)
16730fdc8d8SChris Lattner {
16830fdc8d8SChris Lattner     // If we couldn't set the breakpoint for some reason, then this won't
16930fdc8d8SChris Lattner     // work.
17008b87e0dSJim Ingham     bool all_bps_good = true;
17108b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
17208b87e0dSJim Ingham 
17308b87e0dSJim Ingham     for (size_t i = 0; i < num_break_ids; i++)
17408b87e0dSJim Ingham     {
17508b87e0dSJim Ingham         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
17608b87e0dSJim Ingham         {
17708b87e0dSJim Ingham             all_bps_good = false;
178f48169bbSJim Ingham             if (error)
179f48169bbSJim Ingham             {
18008b87e0dSJim Ingham                 error->Printf ("Could not set breakpoint for address: ");
18108b87e0dSJim Ingham                 error->Address (m_addresses[i], sizeof (addr_t));
18208b87e0dSJim Ingham                 error->Printf ("\n");
18308b87e0dSJim Ingham             }
18408b87e0dSJim Ingham         }
185f48169bbSJim Ingham     }
18608b87e0dSJim Ingham     return all_bps_good;
18730fdc8d8SChris Lattner }
18830fdc8d8SChris Lattner 
18930fdc8d8SChris Lattner bool
19030fdc8d8SChris Lattner ThreadPlanRunToAddress::PlanExplainsStop ()
19130fdc8d8SChris Lattner {
19230fdc8d8SChris Lattner     return AtOurAddress();
19330fdc8d8SChris Lattner }
19430fdc8d8SChris Lattner 
19530fdc8d8SChris Lattner bool
19630fdc8d8SChris Lattner ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
19730fdc8d8SChris Lattner {
19830fdc8d8SChris Lattner     return false;
19930fdc8d8SChris Lattner }
20030fdc8d8SChris Lattner 
20130fdc8d8SChris Lattner bool
20230fdc8d8SChris Lattner ThreadPlanRunToAddress::StopOthers ()
20330fdc8d8SChris Lattner {
20430fdc8d8SChris Lattner     return m_stop_others;
20530fdc8d8SChris Lattner }
20630fdc8d8SChris Lattner 
20730fdc8d8SChris Lattner void
20830fdc8d8SChris Lattner ThreadPlanRunToAddress::SetStopOthers (bool new_value)
20930fdc8d8SChris Lattner {
21030fdc8d8SChris Lattner     m_stop_others = new_value;
21130fdc8d8SChris Lattner }
21230fdc8d8SChris Lattner 
21330fdc8d8SChris Lattner StateType
21406e827ccSJim Ingham ThreadPlanRunToAddress::GetPlanRunState ()
21530fdc8d8SChris Lattner {
21630fdc8d8SChris Lattner     return eStateRunning;
21730fdc8d8SChris Lattner }
21830fdc8d8SChris Lattner 
21930fdc8d8SChris Lattner bool
22030fdc8d8SChris Lattner ThreadPlanRunToAddress::WillStop ()
22130fdc8d8SChris Lattner {
22230fdc8d8SChris Lattner     return true;
22330fdc8d8SChris Lattner }
22430fdc8d8SChris Lattner 
22530fdc8d8SChris Lattner bool
22630fdc8d8SChris Lattner ThreadPlanRunToAddress::MischiefManaged ()
22730fdc8d8SChris Lattner {
2282d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
22930fdc8d8SChris Lattner 
23030fdc8d8SChris Lattner     if (AtOurAddress())
23130fdc8d8SChris Lattner     {
23230fdc8d8SChris Lattner         // Remove the breakpoint
23308b87e0dSJim Ingham         size_t num_break_ids = m_break_ids.size();
23430fdc8d8SChris Lattner 
23508b87e0dSJim Ingham         for (size_t i = 0; i < num_break_ids; i++)
23608b87e0dSJim Ingham         {
23708b87e0dSJim Ingham             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
23808b87e0dSJim Ingham             {
23908b87e0dSJim Ingham                 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
24008b87e0dSJim Ingham                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
24108b87e0dSJim Ingham             }
24208b87e0dSJim Ingham         }
24330fdc8d8SChris Lattner         if (log)
24430fdc8d8SChris Lattner             log->Printf("Completed run to address plan.");
24530fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
24630fdc8d8SChris Lattner         return true;
24730fdc8d8SChris Lattner     }
24830fdc8d8SChris Lattner     else
24930fdc8d8SChris Lattner         return false;
25030fdc8d8SChris Lattner }
25130fdc8d8SChris Lattner 
25230fdc8d8SChris Lattner bool
25330fdc8d8SChris Lattner ThreadPlanRunToAddress::AtOurAddress ()
25430fdc8d8SChris Lattner {
25530fdc8d8SChris Lattner     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
25608b87e0dSJim Ingham     bool found_it = false;
2574bf570d6SJim Ingham     size_t num_addresses = m_addresses.size();
2584bf570d6SJim Ingham     for (size_t i = 0; i < num_addresses; i++)
25908b87e0dSJim Ingham     {
26008b87e0dSJim Ingham         if (m_addresses[i] == current_address)
26108b87e0dSJim Ingham         {
26208b87e0dSJim Ingham             found_it = true;
26308b87e0dSJim Ingham             break;
26408b87e0dSJim Ingham         }
26508b87e0dSJim Ingham     }
26608b87e0dSJim Ingham     return found_it;
26730fdc8d8SChris Lattner }
268