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;
91*eb023e75SGreg Clayton         breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).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
191221d51cfSJim 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