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 ) :
37*08b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
3830fdc8d8SChris Lattner     m_stop_others (stop_others),
39*08b87e0dSJim Ingham     m_addresses (),
40*08b87e0dSJim Ingham     m_break_ids ()
4130fdc8d8SChris Lattner {
42*08b87e0dSJim Ingham     m_addresses.push_back (address.GetLoadAddress(&m_thread.GetProcess()));
43*08b87e0dSJim 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 ) :
52*08b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
5330fdc8d8SChris Lattner     m_stop_others (stop_others),
54*08b87e0dSJim Ingham     m_addresses (),
55*08b87e0dSJim Ingham     m_break_ids ()
5630fdc8d8SChris Lattner {
57*08b87e0dSJim Ingham     m_addresses.push_back(address);
58*08b87e0dSJim Ingham     SetInitialBreakpoints();
59*08b87e0dSJim Ingham }
60*08b87e0dSJim Ingham 
61*08b87e0dSJim Ingham ThreadPlanRunToAddress::ThreadPlanRunToAddress
62*08b87e0dSJim Ingham (
63*08b87e0dSJim Ingham     Thread &thread,
64*08b87e0dSJim Ingham     std::vector<lldb::addr_t> &addresses,
65*08b87e0dSJim Ingham     bool stop_others
66*08b87e0dSJim Ingham ) :
67*08b87e0dSJim Ingham     ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
68*08b87e0dSJim Ingham     m_stop_others (stop_others),
69*08b87e0dSJim Ingham     m_addresses (addresses),
70*08b87e0dSJim Ingham     m_break_ids ()
71*08b87e0dSJim Ingham {
72*08b87e0dSJim Ingham     SetInitialBreakpoints();
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
7530fdc8d8SChris Lattner void
76*08b87e0dSJim Ingham ThreadPlanRunToAddress::SetInitialBreakpoints ()
77*08b87e0dSJim Ingham {
78*08b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
79*08b87e0dSJim Ingham     m_break_ids.resize(num_addresses);
80*08b87e0dSJim Ingham 
81*08b87e0dSJim Ingham     for (size_t i = 0; i < num_addresses; i++)
8230fdc8d8SChris Lattner     {
8330fdc8d8SChris Lattner         Breakpoint *breakpoint;
84*08b87e0dSJim Ingham         breakpoint = m_thread.GetProcess().GetTarget().CreateBreakpoint (m_addresses[i], true).get();
8530fdc8d8SChris Lattner         if (breakpoint != NULL)
8630fdc8d8SChris Lattner         {
87*08b87e0dSJim Ingham             m_break_ids[i] = breakpoint->GetID();
8830fdc8d8SChris Lattner             breakpoint->SetThreadID(m_thread.GetID());
8930fdc8d8SChris Lattner         }
9030fdc8d8SChris Lattner     }
91*08b87e0dSJim Ingham }
9230fdc8d8SChris Lattner 
9330fdc8d8SChris Lattner ThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
9430fdc8d8SChris Lattner {
95*08b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
96*08b87e0dSJim Ingham     for (size_t i = 0; i <  num_break_ids; i++)
9730fdc8d8SChris Lattner     {
98*08b87e0dSJim 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 {
105*08b87e0dSJim Ingham     size_t num_addresses = m_addresses.size();
106*08b87e0dSJim Ingham 
10730fdc8d8SChris Lattner     if (level == lldb::eDescriptionLevelBrief)
10830fdc8d8SChris Lattner     {
109*08b87e0dSJim Ingham         if (num_addresses == 0)
110*08b87e0dSJim Ingham         {
111*08b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
112*08b87e0dSJim Ingham             return;
113*08b87e0dSJim Ingham         }
114*08b87e0dSJim Ingham         else if (num_addresses == 1)
11530fdc8d8SChris Lattner             s->Printf ("run to address: ");
116*08b87e0dSJim Ingham         else
117*08b87e0dSJim Ingham             s->Printf ("run to addresses: ");
118*08b87e0dSJim Ingham 
119*08b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
120*08b87e0dSJim Ingham         {
121*08b87e0dSJim Ingham             s->Address (m_addresses[i], sizeof (addr_t));
122*08b87e0dSJim Ingham             s->Printf(" ");
123*08b87e0dSJim Ingham         }
12430fdc8d8SChris Lattner     }
12530fdc8d8SChris Lattner     else
12630fdc8d8SChris Lattner     {
127*08b87e0dSJim Ingham         if (num_addresses == 0)
128*08b87e0dSJim Ingham         {
129*08b87e0dSJim Ingham             s->Printf ("run to address with no addresses given.");
130*08b87e0dSJim Ingham             return;
131*08b87e0dSJim Ingham         }
132*08b87e0dSJim Ingham         else if (num_addresses == 1)
13330fdc8d8SChris Lattner             s->Printf ("Run to address: ");
134*08b87e0dSJim Ingham         else
135*08b87e0dSJim Ingham         {
136*08b87e0dSJim Ingham             s->Printf ("Run to addresses: ");
137*08b87e0dSJim Ingham         }
138*08b87e0dSJim Ingham 
139*08b87e0dSJim Ingham         for (size_t i = 0; i < num_addresses; i++)
140*08b87e0dSJim Ingham         {
141*08b87e0dSJim Ingham             if (num_addresses > 1)
142*08b87e0dSJim Ingham             {
143*08b87e0dSJim Ingham                 s->Printf("\n");
144*08b87e0dSJim Ingham                 s->Indent();
145*08b87e0dSJim Ingham             }
146*08b87e0dSJim Ingham 
147*08b87e0dSJim Ingham             s->Address(m_addresses[i], sizeof (addr_t));
148*08b87e0dSJim Ingham             s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
149*08b87e0dSJim 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     }
156*08b87e0dSJim 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.
163*08b87e0dSJim Ingham     bool all_bps_good = true;
164*08b87e0dSJim Ingham     size_t num_break_ids = m_break_ids.size();
165*08b87e0dSJim Ingham 
166*08b87e0dSJim Ingham     for (size_t i = 0; i < num_break_ids; i++)
167*08b87e0dSJim Ingham     {
168*08b87e0dSJim Ingham         if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
169*08b87e0dSJim Ingham         {
170*08b87e0dSJim Ingham             all_bps_good = false;
171*08b87e0dSJim Ingham             error->Printf ("Could not set breakpoint for address: ");
172*08b87e0dSJim Ingham             error->Address (m_addresses[i], sizeof (addr_t));
173*08b87e0dSJim Ingham             error->Printf ("\n");
174*08b87e0dSJim Ingham         }
175*08b87e0dSJim Ingham     }
176*08b87e0dSJim Ingham     return all_bps_good;
17730fdc8d8SChris Lattner }
17830fdc8d8SChris Lattner 
17930fdc8d8SChris Lattner bool
18030fdc8d8SChris Lattner ThreadPlanRunToAddress::PlanExplainsStop ()
18130fdc8d8SChris Lattner {
18230fdc8d8SChris Lattner     return AtOurAddress();
18330fdc8d8SChris Lattner }
18430fdc8d8SChris Lattner 
18530fdc8d8SChris Lattner bool
18630fdc8d8SChris Lattner ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
18730fdc8d8SChris Lattner {
18830fdc8d8SChris Lattner     return false;
18930fdc8d8SChris Lattner }
19030fdc8d8SChris Lattner 
19130fdc8d8SChris Lattner bool
19230fdc8d8SChris Lattner ThreadPlanRunToAddress::StopOthers ()
19330fdc8d8SChris Lattner {
19430fdc8d8SChris Lattner     return m_stop_others;
19530fdc8d8SChris Lattner }
19630fdc8d8SChris Lattner 
19730fdc8d8SChris Lattner void
19830fdc8d8SChris Lattner ThreadPlanRunToAddress::SetStopOthers (bool new_value)
19930fdc8d8SChris Lattner {
20030fdc8d8SChris Lattner     m_stop_others = new_value;
20130fdc8d8SChris Lattner }
20230fdc8d8SChris Lattner 
20330fdc8d8SChris Lattner StateType
20430fdc8d8SChris Lattner ThreadPlanRunToAddress::RunState ()
20530fdc8d8SChris Lattner {
20630fdc8d8SChris Lattner     return eStateRunning;
20730fdc8d8SChris Lattner }
20830fdc8d8SChris Lattner 
20930fdc8d8SChris Lattner bool
21030fdc8d8SChris Lattner ThreadPlanRunToAddress::WillStop ()
21130fdc8d8SChris Lattner {
21230fdc8d8SChris Lattner     return true;
21330fdc8d8SChris Lattner }
21430fdc8d8SChris Lattner 
21530fdc8d8SChris Lattner bool
21630fdc8d8SChris Lattner ThreadPlanRunToAddress::MischiefManaged ()
21730fdc8d8SChris Lattner {
21830fdc8d8SChris Lattner     Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
21930fdc8d8SChris Lattner 
22030fdc8d8SChris Lattner     if (AtOurAddress())
22130fdc8d8SChris Lattner     {
22230fdc8d8SChris Lattner         // Remove the breakpoint
223*08b87e0dSJim Ingham         size_t num_break_ids = m_break_ids.size();
22430fdc8d8SChris Lattner 
225*08b87e0dSJim Ingham         for (size_t i = 0; i < num_break_ids; i++)
226*08b87e0dSJim Ingham         {
227*08b87e0dSJim Ingham             if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
228*08b87e0dSJim Ingham             {
229*08b87e0dSJim Ingham                 m_thread.GetProcess().GetTarget().RemoveBreakpointByID (m_break_ids[i]);
230*08b87e0dSJim Ingham                 m_break_ids[i] = LLDB_INVALID_BREAK_ID;
231*08b87e0dSJim Ingham             }
232*08b87e0dSJim Ingham         }
23330fdc8d8SChris Lattner         if (log)
23430fdc8d8SChris Lattner             log->Printf("Completed run to address plan.");
23530fdc8d8SChris Lattner         ThreadPlan::MischiefManaged ();
23630fdc8d8SChris Lattner         return true;
23730fdc8d8SChris Lattner     }
23830fdc8d8SChris Lattner     else
23930fdc8d8SChris Lattner         return false;
24030fdc8d8SChris Lattner }
24130fdc8d8SChris Lattner 
24230fdc8d8SChris Lattner bool
24330fdc8d8SChris Lattner ThreadPlanRunToAddress::AtOurAddress ()
24430fdc8d8SChris Lattner {
24530fdc8d8SChris Lattner     lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
246*08b87e0dSJim Ingham     bool found_it = false;
247*08b87e0dSJim Ingham     for (size_t i = 0; i < m_addresses[i]; i++)
248*08b87e0dSJim Ingham     {
249*08b87e0dSJim Ingham         if (m_addresses[i] == current_address)
250*08b87e0dSJim Ingham         {
251*08b87e0dSJim Ingham             found_it = true;
252*08b87e0dSJim Ingham             break;
253*08b87e0dSJim Ingham         }
254*08b87e0dSJim Ingham     }
255*08b87e0dSJim Ingham     return found_it;
25630fdc8d8SChris Lattner }
257