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 // C Includes
1130fdc8d8SChris Lattner // C++ Includes
1230fdc8d8SChris Lattner // Other libraries and framework includes
1330fdc8d8SChris Lattner // Project includes
14*e65b2cf2SEugene Zelenko #include "lldb/Target/ThreadPlanRunToAddress.h"
1530fdc8d8SChris Lattner #include "lldb/Core/Log.h"
1630fdc8d8SChris Lattner #include "lldb/Core/Stream.h"
1730fdc8d8SChris Lattner #include "lldb/Target/Target.h"
1830fdc8d8SChris Lattner #include "lldb/Target/Process.h"
1930fdc8d8SChris Lattner #include "lldb/Target/Thread.h"
2030fdc8d8SChris Lattner #include "lldb/Target/RegisterContext.h"
2130fdc8d8SChris Lattner 
2230fdc8d8SChris Lattner using namespace lldb;
2330fdc8d8SChris Lattner using namespace lldb_private;
2430fdc8d8SChris Lattner 
2530fdc8d8SChris Lattner //----------------------------------------------------------------------
2630fdc8d8SChris Lattner // ThreadPlanRunToAddress: Continue plan
2730fdc8d8SChris Lattner //----------------------------------------------------------------------
2830fdc8d8SChris Lattner 
2930fdc8d8SChris Lattner ThreadPlanRunToAddress::ThreadPlanRunToAddress
3030fdc8d8SChris Lattner (
3130fdc8d8SChris Lattner     Thread &thread,
3230fdc8d8SChris Lattner     Address &address,
3330fdc8d8SChris Lattner     bool stop_others
3430fdc8d8SChris Lattner ) :
3508b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
3630fdc8d8SChris Lattner     m_stop_others (stop_others),
3708b87e0dSJim Ingham     m_addresses (),
3808b87e0dSJim Ingham     m_break_ids ()
3930fdc8d8SChris Lattner {
401ac04c30SGreg Clayton     m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get()));
4108b87e0dSJim Ingham     SetInitialBreakpoints();
4230fdc8d8SChris Lattner }
4330fdc8d8SChris Lattner 
4430fdc8d8SChris Lattner ThreadPlanRunToAddress::ThreadPlanRunToAddress
4530fdc8d8SChris Lattner (
4630fdc8d8SChris Lattner     Thread &thread,
4730fdc8d8SChris Lattner     lldb::addr_t address,
4830fdc8d8SChris Lattner     bool stop_others
4930fdc8d8SChris Lattner ) :
5008b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
5130fdc8d8SChris Lattner     m_stop_others (stop_others),
5208b87e0dSJim Ingham     m_addresses (),
5308b87e0dSJim Ingham     m_break_ids ()
5430fdc8d8SChris Lattner {
551ac04c30SGreg Clayton     m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
5608b87e0dSJim Ingham     SetInitialBreakpoints();
5708b87e0dSJim Ingham }
5808b87e0dSJim Ingham 
5908b87e0dSJim Ingham ThreadPlanRunToAddress::ThreadPlanRunToAddress
6008b87e0dSJim Ingham (
6108b87e0dSJim Ingham     Thread &thread,
62f3ef3d2aSGreg Clayton     const std::vector<lldb::addr_t> &addresses,
6308b87e0dSJim Ingham     bool stop_others
6408b87e0dSJim Ingham ) :
6508b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
6608b87e0dSJim Ingham     m_stop_others (stop_others),
6708b87e0dSJim Ingham     m_addresses (addresses),
6808b87e0dSJim Ingham     m_break_ids ()
6908b87e0dSJim Ingham {
70d93c4a33SBruce Mitchener     // Convert all addresses into opcode addresses to make sure we set
71f3ef3d2aSGreg Clayton     // breakpoints at the correct address.
721ac04c30SGreg Clayton     Target &target = thread.GetProcess()->GetTarget();
73f3ef3d2aSGreg Clayton     std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
74f3ef3d2aSGreg Clayton     for (pos = m_addresses.begin(); pos != end; ++pos)
75f3ef3d2aSGreg Clayton         *pos = target.GetOpcodeLoadAddress (*pos);
76f3ef3d2aSGreg Clayton 
7708b87e0dSJim Ingham     SetInitialBreakpoints();
7830fdc8d8SChris Lattner }
7930fdc8d8SChris Lattner 
8030fdc8d8SChris Lattner void
8108b87e0dSJim Ingham ThreadPlanRunToAddress::SetInitialBreakpoints ()
8208b87e0dSJim Ingham {
8308b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
8408b87e0dSJim Ingham     m_break_ids.resize(num_addresses);
8508b87e0dSJim Ingham 
8608b87e0dSJim Ingham     for (size_t i = 0; i < num_addresses; i++)
8730fdc8d8SChris Lattner     {
8830fdc8d8SChris Lattner         Breakpoint *breakpoint;
89eb023e75SGreg Clayton         breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get();
90*e65b2cf2SEugene Zelenko         if (breakpoint != nullptr)
9130fdc8d8SChris Lattner         {
9208b87e0dSJim Ingham             m_break_ids[i] = breakpoint->GetID();
9330fdc8d8SChris Lattner             breakpoint->SetThreadID(m_thread.GetID());
942995077dSJim Ingham             breakpoint->SetBreakpointKind("run-to-address");
9530fdc8d8SChris Lattner         }
9630fdc8d8SChris Lattner     }
9708b87e0dSJim Ingham }
9830fdc8d8SChris Lattner 
9930fdc8d8SChris Lattner ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
10030fdc8d8SChris Lattner {
10108b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
10208b87e0dSJim Ingham     for (size_t i = 0; i <  num_break_ids; i++)
10330fdc8d8SChris Lattner     {
1041ac04c30SGreg Clayton         m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
10530fdc8d8SChris Lattner     }
10630fdc8d8SChris Lattner }
10730fdc8d8SChris Lattner 
10830fdc8d8SChris Lattner void
10930fdc8d8SChris Lattner ThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
11030fdc8d8SChris Lattner {
11108b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
11208b87e0dSJim Ingham 
11330fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
11430fdc8d8SChris Lattner     {
11508b87e0dSJim Ingham         if (num_addresses == 0)
11608b87e0dSJim Ingham         {
11708b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
11808b87e0dSJim Ingham             return;
11908b87e0dSJim Ingham         }
12008b87e0dSJim Ingham         else if (num_addresses == 1)
12130fdc8d8SChris Lattner             s->Printf ("run to address: ");
12208b87e0dSJim Ingham         else
12308b87e0dSJim Ingham             s->Printf ("run to addresses: ");
12408b87e0dSJim Ingham 
12508b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
12608b87e0dSJim Ingham         {
12708b87e0dSJim Ingham             s->Address (m_addresses[i], sizeof (addr_t));
12808b87e0dSJim Ingham             s->Printf(" ");
12908b87e0dSJim Ingham         }
13030fdc8d8SChris Lattner     }
13130fdc8d8SChris Lattner     else
13230fdc8d8SChris Lattner     {
13308b87e0dSJim Ingham         if (num_addresses == 0)
13408b87e0dSJim Ingham         {
13508b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
13608b87e0dSJim Ingham             return;
13708b87e0dSJim Ingham         }
13808b87e0dSJim Ingham         else if (num_addresses == 1)
13930fdc8d8SChris Lattner             s->Printf ("Run to address: ");
14008b87e0dSJim Ingham         else
14108b87e0dSJim Ingham         {
14208b87e0dSJim Ingham             s->Printf ("Run to addresses: ");
14308b87e0dSJim Ingham         }
14408b87e0dSJim Ingham 
14508b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
14608b87e0dSJim Ingham         {
14708b87e0dSJim Ingham             if (num_addresses > 1)
14808b87e0dSJim Ingham             {
14908b87e0dSJim Ingham                 s->Printf("\n");
15008b87e0dSJim Ingham                 s->Indent();
15108b87e0dSJim Ingham             }
15208b87e0dSJim Ingham 
15308b87e0dSJim Ingham             s->Address(m_addresses[i], sizeof (addr_t));
154f58a0487SJim Ingham             s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
1551ac04c30SGreg Clayton             Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get();
15630fdc8d8SChris Lattner             if (breakpoint)
15730fdc8d8SChris Lattner                 breakpoint->Dump (s);
15830fdc8d8SChris Lattner             else
15930fdc8d8SChris Lattner                 s->Printf ("but the breakpoint has been deleted.");
16030fdc8d8SChris Lattner         }
16130fdc8d8SChris Lattner     }
16208b87e0dSJim Ingham }
16330fdc8d8SChris Lattner 
16430fdc8d8SChris Lattner bool
16530fdc8d8SChris Lattner ThreadPlanRunToAddress::ValidatePlan (Stream *error)
16630fdc8d8SChris Lattner {
16730fdc8d8SChris Lattner     // If we couldn't set the breakpoint for some reason, then this won't
16830fdc8d8SChris Lattner     // work.
16908b87e0dSJim Ingham     bool all_bps_good = true;
17008b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
17108b87e0dSJim Ingham 
17208b87e0dSJim Ingham     for (size_t i = 0; i < num_break_ids; i++)
17308b87e0dSJim Ingham     {
17408b87e0dSJim Ingham         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
17508b87e0dSJim Ingham         {
17608b87e0dSJim Ingham             all_bps_good = false;
177f48169bbSJim Ingham             if (error)
178f48169bbSJim Ingham             {
17908b87e0dSJim Ingham                 error->Printf ("Could not set breakpoint for address: ");
18008b87e0dSJim Ingham                 error->Address (m_addresses[i], sizeof (addr_t));
18108b87e0dSJim Ingham                 error->Printf ("\n");
18208b87e0dSJim Ingham             }
18308b87e0dSJim Ingham         }
184f48169bbSJim Ingham     }
18508b87e0dSJim Ingham     return all_bps_good;
18630fdc8d8SChris Lattner }
18730fdc8d8SChris Lattner 
18830fdc8d8SChris Lattner bool
189221d51cfSJim Ingham ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
19030fdc8d8SChris Lattner {
19130fdc8d8SChris Lattner     return AtOurAddress();
19230fdc8d8SChris Lattner }
19330fdc8d8SChris Lattner 
19430fdc8d8SChris Lattner bool
19530fdc8d8SChris Lattner ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
19630fdc8d8SChris Lattner {
1971fd2f08eSJim Ingham     return AtOurAddress();
19830fdc8d8SChris Lattner }
19930fdc8d8SChris Lattner 
20030fdc8d8SChris Lattner bool
20130fdc8d8SChris Lattner ThreadPlanRunToAddress::StopOthers ()
20230fdc8d8SChris Lattner {
20330fdc8d8SChris Lattner     return m_stop_others;
20430fdc8d8SChris Lattner }
20530fdc8d8SChris Lattner 
20630fdc8d8SChris Lattner void
20730fdc8d8SChris Lattner ThreadPlanRunToAddress::SetStopOthers (bool new_value)
20830fdc8d8SChris Lattner {
20930fdc8d8SChris Lattner     m_stop_others = new_value;
21030fdc8d8SChris Lattner }
21130fdc8d8SChris Lattner 
21230fdc8d8SChris Lattner StateType
21306e827ccSJim Ingham ThreadPlanRunToAddress::GetPlanRunState ()
21430fdc8d8SChris Lattner {
21530fdc8d8SChris Lattner     return eStateRunning;
21630fdc8d8SChris Lattner }
21730fdc8d8SChris Lattner 
21830fdc8d8SChris Lattner bool
21930fdc8d8SChris Lattner ThreadPlanRunToAddress::WillStop ()
22030fdc8d8SChris Lattner {
22130fdc8d8SChris Lattner     return true;
22230fdc8d8SChris Lattner }
22330fdc8d8SChris Lattner 
22430fdc8d8SChris Lattner bool
22530fdc8d8SChris Lattner ThreadPlanRunToAddress::MischiefManaged ()
22630fdc8d8SChris Lattner {
2275160ce5cSGreg Clayton     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
22830fdc8d8SChris Lattner 
22930fdc8d8SChris Lattner     if (AtOurAddress())
23030fdc8d8SChris Lattner     {
23130fdc8d8SChris Lattner         // Remove the breakpoint
23208b87e0dSJim Ingham         size_t num_break_ids = m_break_ids.size();
23330fdc8d8SChris Lattner 
23408b87e0dSJim Ingham         for (size_t i = 0; i < num_break_ids; i++)
23508b87e0dSJim Ingham         {
23608b87e0dSJim Ingham             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
23708b87e0dSJim Ingham             {
2381ac04c30SGreg Clayton                 m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
23908b87e0dSJim Ingham                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
24008b87e0dSJim Ingham             }
24108b87e0dSJim Ingham         }
24230fdc8d8SChris Lattner         if (log)
24330fdc8d8SChris Lattner             log->Printf("Completed run to address plan.");
24430fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
24530fdc8d8SChris Lattner         return true;
24630fdc8d8SChris Lattner     }
24730fdc8d8SChris Lattner     else
24830fdc8d8SChris Lattner         return false;
24930fdc8d8SChris Lattner }
25030fdc8d8SChris Lattner 
25130fdc8d8SChris Lattner bool
25230fdc8d8SChris Lattner ThreadPlanRunToAddress::AtOurAddress ()
25330fdc8d8SChris Lattner {
25430fdc8d8SChris Lattner     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
25508b87e0dSJim Ingham     bool found_it = false;
2564bf570d6SJim Ingham     size_t num_addresses = m_addresses.size();
2574bf570d6SJim Ingham     for (size_t i = 0; i < num_addresses; i++)
25808b87e0dSJim Ingham     {
25908b87e0dSJim Ingham         if (m_addresses[i] == current_address)
26008b87e0dSJim Ingham         {
26108b87e0dSJim Ingham             found_it = true;
26208b87e0dSJim Ingham             break;
26308b87e0dSJim Ingham         }
26408b87e0dSJim Ingham     }
26508b87e0dSJim Ingham     return found_it;
26630fdc8d8SChris Lattner }
267