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 {
42f5e56de0SGreg Clayton     m_addresses.push_back (address.GetLoadAddress(&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 {
5708b87e0dSJim Ingham     m_addresses.push_back(address);
5808b87e0dSJim Ingham     SetInitialBreakpoints();
5908b87e0dSJim Ingham }
6008b87e0dSJim Ingham 
6108b87e0dSJim Ingham ThreadPlanRunToAddress::ThreadPlanRunToAddress
6208b87e0dSJim Ingham (
6308b87e0dSJim Ingham     Thread &thread,
6408b87e0dSJim Ingham     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 {
7208b87e0dSJim Ingham     SetInitialBreakpoints();
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
7530fdc8d8SChris Lattner void
7608b87e0dSJim Ingham ThreadPlanRunToAddress::SetInitialBreakpoints ()
7708b87e0dSJim Ingham {
7808b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
7908b87e0dSJim Ingham     m_break_ids.resize(num_addresses);
8008b87e0dSJim Ingham 
8108b87e0dSJim Ingham     for (size_t i = 0; i < num_addresses; i++)
8230fdc8d8SChris Lattner     {
8330fdc8d8SChris Lattner         Breakpoint *breakpoint;
8408b87e0dSJim Ingham         breakpoint = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_addresses[i], true).get();
8530fdc8d8SChris Lattner         if (breakpoint != NULL)
8630fdc8d8SChris Lattner         {
8708b87e0dSJim Ingham             m_break_ids[i] = breakpoint->GetID();
8830fdc8d8SChris Lattner             breakpoint->SetThreadID(m_thread.GetID());
8930fdc8d8SChris Lattner         }
9030fdc8d8SChris Lattner     }
9108b87e0dSJim Ingham }
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
9430fdc8d8SChris Lattner {
9508b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
9608b87e0dSJim Ingham     for (size_t i = 0; i <  num_break_ids; i++)
9730fdc8d8SChris Lattner     {
9808b87e0dSJim Ingham         m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
9930fdc8d8SChris Lattner     }
10030fdc8d8SChris Lattner }
10130fdc8d8SChris Lattner 
10230fdc8d8SChris Lattner void
10330fdc8d8SChris Lattner ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
10430fdc8d8SChris Lattner {
10508b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
10608b87e0dSJim Ingham 
10730fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
10830fdc8d8SChris Lattner     {
10908b87e0dSJim Ingham         if (num_addresses == 0)
11008b87e0dSJim Ingham         {
11108b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
11208b87e0dSJim Ingham             return;
11308b87e0dSJim Ingham         }
11408b87e0dSJim Ingham         else if (num_addresses == 1)
11530fdc8d8SChris Lattner             s->Printf ("run to address: ");
11608b87e0dSJim Ingham         else
11708b87e0dSJim Ingham             s->Printf ("run to addresses: ");
11808b87e0dSJim Ingham 
11908b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
12008b87e0dSJim Ingham         {
12108b87e0dSJim Ingham             s->Address (m_addresses[i], sizeof (addr_t));
12208b87e0dSJim Ingham             s->Printf(" ");
12308b87e0dSJim Ingham         }
12430fdc8d8SChris Lattner     }
12530fdc8d8SChris Lattner     else
12630fdc8d8SChris Lattner     {
12708b87e0dSJim Ingham         if (num_addresses == 0)
12808b87e0dSJim Ingham         {
12908b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
13008b87e0dSJim Ingham             return;
13108b87e0dSJim Ingham         }
13208b87e0dSJim Ingham         else if (num_addresses == 1)
13330fdc8d8SChris Lattner             s->Printf ("Run to address: ");
13408b87e0dSJim Ingham         else
13508b87e0dSJim Ingham         {
13608b87e0dSJim Ingham             s->Printf ("Run to addresses: ");
13708b87e0dSJim Ingham         }
13808b87e0dSJim Ingham 
13908b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
14008b87e0dSJim Ingham         {
14108b87e0dSJim Ingham             if (num_addresses > 1)
14208b87e0dSJim Ingham             {
14308b87e0dSJim Ingham                 s->Printf("\n");
14408b87e0dSJim Ingham                 s->Indent();
14508b87e0dSJim Ingham             }
14608b87e0dSJim Ingham 
14708b87e0dSJim Ingham             s->Address(m_addresses[i], sizeof (addr_t));
14808b87e0dSJim Ingham             s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
14908b87e0dSJim Ingham             Breakpoint *breakpoint = m_thread.GetProcess().GetTarget().GetBreakpointByID (m_break_ids[i]).get();
15030fdc8d8SChris Lattner             if (breakpoint)
15130fdc8d8SChris Lattner                 breakpoint->Dump (s);
15230fdc8d8SChris Lattner             else
15330fdc8d8SChris Lattner                 s->Printf ("but the breakpoint has been deleted.");
15430fdc8d8SChris Lattner         }
15530fdc8d8SChris Lattner     }
15608b87e0dSJim Ingham }
15730fdc8d8SChris Lattner 
15830fdc8d8SChris Lattner bool
15930fdc8d8SChris Lattner ThreadPlanRunToAddress::ValidatePlan (Stream *error)
16030fdc8d8SChris Lattner {
16130fdc8d8SChris Lattner     // If we couldn't set the breakpoint for some reason, then this won't
16230fdc8d8SChris Lattner     // work.
16308b87e0dSJim Ingham     bool all_bps_good = true;
16408b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
16508b87e0dSJim Ingham 
16608b87e0dSJim Ingham     for (size_t i = 0; i < num_break_ids; i++)
16708b87e0dSJim Ingham     {
16808b87e0dSJim Ingham         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
16908b87e0dSJim Ingham         {
17008b87e0dSJim Ingham             all_bps_good = false;
171*f48169bbSJim Ingham             if (error)
172*f48169bbSJim Ingham             {
17308b87e0dSJim Ingham                 error->Printf ("Could not set breakpoint for address: ");
17408b87e0dSJim Ingham                 error->Address (m_addresses[i], sizeof (addr_t));
17508b87e0dSJim Ingham                 error->Printf ("\n");
17608b87e0dSJim Ingham             }
17708b87e0dSJim Ingham         }
178*f48169bbSJim Ingham     }
17908b87e0dSJim Ingham     return all_bps_good;
18030fdc8d8SChris Lattner }
18130fdc8d8SChris Lattner 
18230fdc8d8SChris Lattner bool
18330fdc8d8SChris Lattner ThreadPlanRunToAddress::PlanExplainsStop ()
18430fdc8d8SChris Lattner {
18530fdc8d8SChris Lattner     return AtOurAddress();
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner 
18830fdc8d8SChris Lattner bool
18930fdc8d8SChris Lattner ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
19030fdc8d8SChris Lattner {
19130fdc8d8SChris Lattner     return false;
19230fdc8d8SChris Lattner }
19330fdc8d8SChris Lattner 
19430fdc8d8SChris Lattner bool
19530fdc8d8SChris Lattner ThreadPlanRunToAddress::StopOthers ()
19630fdc8d8SChris Lattner {
19730fdc8d8SChris Lattner     return m_stop_others;
19830fdc8d8SChris Lattner }
19930fdc8d8SChris Lattner 
20030fdc8d8SChris Lattner void
20130fdc8d8SChris Lattner ThreadPlanRunToAddress::SetStopOthers (bool new_value)
20230fdc8d8SChris Lattner {
20330fdc8d8SChris Lattner     m_stop_others = new_value;
20430fdc8d8SChris Lattner }
20530fdc8d8SChris Lattner 
20630fdc8d8SChris Lattner StateType
20706e827ccSJim Ingham ThreadPlanRunToAddress::GetPlanRunState ()
20830fdc8d8SChris Lattner {
20930fdc8d8SChris Lattner     return eStateRunning;
21030fdc8d8SChris Lattner }
21130fdc8d8SChris Lattner 
21230fdc8d8SChris Lattner bool
21330fdc8d8SChris Lattner ThreadPlanRunToAddress::WillStop ()
21430fdc8d8SChris Lattner {
21530fdc8d8SChris Lattner     return true;
21630fdc8d8SChris Lattner }
21730fdc8d8SChris Lattner 
21830fdc8d8SChris Lattner bool
21930fdc8d8SChris Lattner ThreadPlanRunToAddress::MischiefManaged ()
22030fdc8d8SChris Lattner {
2212d4edfbcSGreg Clayton     LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
22230fdc8d8SChris Lattner 
22330fdc8d8SChris Lattner     if (AtOurAddress())
22430fdc8d8SChris Lattner     {
22530fdc8d8SChris Lattner         // Remove the breakpoint
22608b87e0dSJim Ingham         size_t num_break_ids = m_break_ids.size();
22730fdc8d8SChris Lattner 
22808b87e0dSJim Ingham         for (size_t i = 0; i < num_break_ids; i++)
22908b87e0dSJim Ingham         {
23008b87e0dSJim Ingham             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
23108b87e0dSJim Ingham             {
23208b87e0dSJim Ingham                 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
23308b87e0dSJim Ingham                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
23408b87e0dSJim Ingham             }
23508b87e0dSJim Ingham         }
23630fdc8d8SChris Lattner         if (log)
23730fdc8d8SChris Lattner             log->Printf("Completed run to address plan.");
23830fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
23930fdc8d8SChris Lattner         return true;
24030fdc8d8SChris Lattner     }
24130fdc8d8SChris Lattner     else
24230fdc8d8SChris Lattner         return false;
24330fdc8d8SChris Lattner }
24430fdc8d8SChris Lattner 
24530fdc8d8SChris Lattner bool
24630fdc8d8SChris Lattner ThreadPlanRunToAddress::AtOurAddress ()
24730fdc8d8SChris Lattner {
24830fdc8d8SChris Lattner     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
24908b87e0dSJim Ingham     bool found_it = false;
25008b87e0dSJim Ingham     for (size_t i = 0; i < m_addresses[i]; i++)
25108b87e0dSJim Ingham     {
25208b87e0dSJim Ingham         if (m_addresses[i] == current_address)
25308b87e0dSJim Ingham         {
25408b87e0dSJim Ingham             found_it = true;
25508b87e0dSJim Ingham             break;
25608b87e0dSJim Ingham         }
25708b87e0dSJim Ingham     }
25808b87e0dSJim Ingham     return found_it;
25930fdc8d8SChris Lattner }
260