1254721Semaste//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
2254721Semaste//
3254721Semaste//                     The LLVM Compiler Infrastructure
4254721Semaste//
5254721Semaste// This file is distributed under the University of Illinois Open Source
6254721Semaste// License. See LICENSE.TXT for details.
7254721Semaste//
8254721Semaste//===----------------------------------------------------------------------===//
9254721Semaste
10254721Semaste#include "lldb/Target/ThreadPlanRunToAddress.h"
11254721Semaste
12254721Semaste// C Includes
13254721Semaste// C++ Includes
14254721Semaste// Other libraries and framework includes
15254721Semaste// Project includes
16254721Semaste#include "lldb/lldb-private-log.h"
17254721Semaste#include "lldb/Core/Log.h"
18254721Semaste#include "lldb/Core/Stream.h"
19254721Semaste#include "lldb/Target/Target.h"
20254721Semaste#include "lldb/Target/Process.h"
21254721Semaste#include "lldb/Target/Thread.h"
22254721Semaste#include "lldb/Target/RegisterContext.h"
23254721Semaste
24254721Semasteusing namespace lldb;
25254721Semasteusing namespace lldb_private;
26254721Semaste
27254721Semaste//----------------------------------------------------------------------
28254721Semaste// ThreadPlanRunToAddress: Continue plan
29254721Semaste//----------------------------------------------------------------------
30254721Semaste
31254721SemasteThreadPlanRunToAddress::ThreadPlanRunToAddress
32254721Semaste(
33254721Semaste    Thread &thread,
34254721Semaste    Address &address,
35254721Semaste    bool stop_others
36254721Semaste) :
37254721Semaste    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
38254721Semaste    m_stop_others (stop_others),
39254721Semaste    m_addresses (),
40254721Semaste    m_break_ids ()
41254721Semaste{
42254721Semaste    m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get()));
43254721Semaste    SetInitialBreakpoints();
44254721Semaste}
45254721Semaste
46254721SemasteThreadPlanRunToAddress::ThreadPlanRunToAddress
47254721Semaste(
48254721Semaste    Thread &thread,
49254721Semaste    lldb::addr_t address,
50254721Semaste    bool stop_others
51254721Semaste) :
52254721Semaste    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
53254721Semaste    m_stop_others (stop_others),
54254721Semaste    m_addresses (),
55254721Semaste    m_break_ids ()
56254721Semaste{
57254721Semaste    m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
58254721Semaste    SetInitialBreakpoints();
59254721Semaste}
60254721Semaste
61254721SemasteThreadPlanRunToAddress::ThreadPlanRunToAddress
62254721Semaste(
63254721Semaste    Thread &thread,
64254721Semaste    const std::vector<lldb::addr_t> &addresses,
65254721Semaste    bool stop_others
66254721Semaste) :
67254721Semaste    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
68254721Semaste    m_stop_others (stop_others),
69254721Semaste    m_addresses (addresses),
70254721Semaste    m_break_ids ()
71254721Semaste{
72254721Semaste    // Convert all addressses into opcode addresses to make sure we set
73254721Semaste    // breakpoints at the correct address.
74254721Semaste    Target &target = thread.GetProcess()->GetTarget();
75254721Semaste    std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
76254721Semaste    for (pos = m_addresses.begin(); pos != end; ++pos)
77254721Semaste        *pos = target.GetOpcodeLoadAddress (*pos);
78254721Semaste
79254721Semaste    SetInitialBreakpoints();
80254721Semaste}
81254721Semaste
82254721Semastevoid
83254721SemasteThreadPlanRunToAddress::SetInitialBreakpoints ()
84254721Semaste{
85254721Semaste    size_t num_addresses = m_addresses.size();
86254721Semaste    m_break_ids.resize(num_addresses);
87254721Semaste
88254721Semaste    for (size_t i = 0; i < num_addresses; i++)
89254721Semaste    {
90254721Semaste        Breakpoint *breakpoint;
91263363Semaste        breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true, false).get();
92254721Semaste        if (breakpoint != NULL)
93254721Semaste        {
94254721Semaste            m_break_ids[i] = breakpoint->GetID();
95254721Semaste            breakpoint->SetThreadID(m_thread.GetID());
96254721Semaste            breakpoint->SetBreakpointKind("run-to-address");
97254721Semaste        }
98254721Semaste    }
99254721Semaste}
100254721Semaste
101254721SemasteThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
102254721Semaste{
103254721Semaste    size_t num_break_ids = m_break_ids.size();
104254721Semaste    for (size_t i = 0; i <  num_break_ids; i++)
105254721Semaste    {
106254721Semaste        m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
107254721Semaste    }
108254721Semaste}
109254721Semaste
110254721Semastevoid
111254721SemasteThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
112254721Semaste{
113254721Semaste    size_t num_addresses = m_addresses.size();
114254721Semaste
115254721Semaste    if (level == lldb::eDescriptionLevelBrief)
116254721Semaste    {
117254721Semaste        if (num_addresses == 0)
118254721Semaste        {
119254721Semaste            s->Printf ("run to address with no addresses given.");
120254721Semaste            return;
121254721Semaste        }
122254721Semaste        else if (num_addresses == 1)
123254721Semaste            s->Printf ("run to address: ");
124254721Semaste        else
125254721Semaste            s->Printf ("run to addresses: ");
126254721Semaste
127254721Semaste        for (size_t i = 0; i < num_addresses; i++)
128254721Semaste        {
129254721Semaste            s->Address (m_addresses[i], sizeof (addr_t));
130254721Semaste            s->Printf(" ");
131254721Semaste        }
132254721Semaste    }
133254721Semaste    else
134254721Semaste    {
135254721Semaste        if (num_addresses == 0)
136254721Semaste        {
137254721Semaste            s->Printf ("run to address with no addresses given.");
138254721Semaste            return;
139254721Semaste        }
140254721Semaste        else if (num_addresses == 1)
141254721Semaste            s->Printf ("Run to address: ");
142254721Semaste        else
143254721Semaste        {
144254721Semaste            s->Printf ("Run to addresses: ");
145254721Semaste        }
146254721Semaste
147254721Semaste        for (size_t i = 0; i < num_addresses; i++)
148254721Semaste        {
149254721Semaste            if (num_addresses > 1)
150254721Semaste            {
151254721Semaste                s->Printf("\n");
152254721Semaste                s->Indent();
153254721Semaste            }
154254721Semaste
155254721Semaste            s->Address(m_addresses[i], sizeof (addr_t));
156254721Semaste            s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
157254721Semaste            Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get();
158254721Semaste            if (breakpoint)
159254721Semaste                breakpoint->Dump (s);
160254721Semaste            else
161254721Semaste                s->Printf ("but the breakpoint has been deleted.");
162254721Semaste        }
163254721Semaste    }
164254721Semaste}
165254721Semaste
166254721Semastebool
167254721SemasteThreadPlanRunToAddress::ValidatePlan (Stream *error)
168254721Semaste{
169254721Semaste    // If we couldn't set the breakpoint for some reason, then this won't
170254721Semaste    // work.
171254721Semaste    bool all_bps_good = true;
172254721Semaste    size_t num_break_ids = m_break_ids.size();
173254721Semaste
174254721Semaste    for (size_t i = 0; i < num_break_ids; i++)
175254721Semaste    {
176254721Semaste        if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
177254721Semaste        {
178254721Semaste            all_bps_good = false;
179254721Semaste            if (error)
180254721Semaste            {
181254721Semaste                error->Printf ("Could not set breakpoint for address: ");
182254721Semaste                error->Address (m_addresses[i], sizeof (addr_t));
183254721Semaste                error->Printf ("\n");
184254721Semaste            }
185254721Semaste        }
186254721Semaste    }
187254721Semaste    return all_bps_good;
188254721Semaste}
189254721Semaste
190254721Semastebool
191254721SemasteThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
192254721Semaste{
193254721Semaste    return AtOurAddress();
194254721Semaste}
195254721Semaste
196254721Semastebool
197254721SemasteThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
198254721Semaste{
199254721Semaste    return false;
200254721Semaste}
201254721Semaste
202254721Semastebool
203254721SemasteThreadPlanRunToAddress::StopOthers ()
204254721Semaste{
205254721Semaste    return m_stop_others;
206254721Semaste}
207254721Semaste
208254721Semastevoid
209254721SemasteThreadPlanRunToAddress::SetStopOthers (bool new_value)
210254721Semaste{
211254721Semaste    m_stop_others = new_value;
212254721Semaste}
213254721Semaste
214254721SemasteStateType
215254721SemasteThreadPlanRunToAddress::GetPlanRunState ()
216254721Semaste{
217254721Semaste    return eStateRunning;
218254721Semaste}
219254721Semaste
220254721Semastebool
221254721SemasteThreadPlanRunToAddress::WillStop ()
222254721Semaste{
223254721Semaste    return true;
224254721Semaste}
225254721Semaste
226254721Semastebool
227254721SemasteThreadPlanRunToAddress::MischiefManaged ()
228254721Semaste{
229254721Semaste    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
230254721Semaste
231254721Semaste    if (AtOurAddress())
232254721Semaste    {
233254721Semaste        // Remove the breakpoint
234254721Semaste        size_t num_break_ids = m_break_ids.size();
235254721Semaste
236254721Semaste        for (size_t i = 0; i < num_break_ids; i++)
237254721Semaste        {
238254721Semaste            if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
239254721Semaste            {
240254721Semaste                m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
241254721Semaste                m_break_ids[i] = LLDB_INVALID_BREAK_ID;
242254721Semaste            }
243254721Semaste        }
244254721Semaste        if (log)
245254721Semaste            log->Printf("Completed run to address plan.");
246254721Semaste        ThreadPlan::MischiefManaged ();
247254721Semaste        return true;
248254721Semaste    }
249254721Semaste    else
250254721Semaste        return false;
251254721Semaste}
252254721Semaste
253254721Semastebool
254254721SemasteThreadPlanRunToAddress::AtOurAddress ()
255254721Semaste{
256254721Semaste    lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
257254721Semaste    bool found_it = false;
258254721Semaste    size_t num_addresses = m_addresses.size();
259254721Semaste    for (size_t i = 0; i < num_addresses; i++)
260254721Semaste    {
261254721Semaste        if (m_addresses[i] == current_address)
262254721Semaste        {
263254721Semaste            found_it = true;
264254721Semaste            break;
265254721Semaste        }
266254721Semaste    }
267254721Semaste    return found_it;
268254721Semaste}
269