184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//
384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//                     The LLVM Compiler Infrastructure
484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//
584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// This file is distributed under the University of Illinois Open Source
684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// License. See LICENSE.TXT for details.
784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//
884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//===----------------------------------------------------------------------===//
984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
1084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Target/ThreadPlanRunToAddress.h"
1184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
1284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// C Includes
1384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// C++ Includes
1484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// Other libraries and framework includes
1584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// Project includes
1684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/lldb-private-log.h"
1784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Core/Log.h"
1884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Core/Stream.h"
1984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Target/Target.h"
2084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Target/Process.h"
2184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Target/Thread.h"
2284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans#include "lldb/Target/RegisterContext.h"
2384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
2484cbbcb90af44807361198baed4e74ab77715ff7Jason Evansusing namespace lldb;
2584cbbcb90af44807361198baed4e74ab77715ff7Jason Evansusing namespace lldb_private;
2684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
2784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//----------------------------------------------------------------------
2884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans// ThreadPlanRunToAddress: Continue plan
2984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans//----------------------------------------------------------------------
3084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
3184cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::ThreadPlanRunToAddress
3284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans(
3384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    Thread &thread,
3484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    Address &address,
3584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    bool stop_others
3684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans) :
3784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
3884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_stop_others (stop_others),
3984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_addresses (),
4084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_break_ids ()
4184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
4284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_addresses.push_back (address.GetOpcodeLoadAddress (m_thread.CalculateTarget().get()));
4384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    SetInitialBreakpoints();
4484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans}
4584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
4684cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::ThreadPlanRunToAddress
4784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans(
4884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    Thread &thread,
4984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    lldb::addr_t address,
5084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    bool stop_others
5184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans) :
5284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
5384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_stop_others (stop_others),
5484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_addresses (),
5584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_break_ids ()
5684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
5784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_addresses.push_back(m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
5884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    SetInitialBreakpoints();
5984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans}
6084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
6184cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::ThreadPlanRunToAddress
6284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans(
6384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    Thread &thread,
6484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    const std::vector<lldb::addr_t> &addresses,
6584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    bool stop_others
6684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans) :
6784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    ThreadPlan (ThreadPlan::eKindRunToAddress, "Run to address plan", thread, eVoteNoOpinion, eVoteNoOpinion),
6884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_stop_others (stop_others),
6984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_addresses (addresses),
7084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_break_ids ()
7184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
7284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    // Convert all addressses into opcode addresses to make sure we set
7384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    // breakpoints at the correct address.
7484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    Target &target = thread.GetProcess()->GetTarget();
7584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
7684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    for (pos = m_addresses.begin(); pos != end; ++pos)
7784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        *pos = target.GetOpcodeLoadAddress (*pos);
7884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
7984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    SetInitialBreakpoints();
8084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans}
8184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
8284cbbcb90af44807361198baed4e74ab77715ff7Jason Evansvoid
8384cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::SetInitialBreakpoints ()
8484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
8584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    size_t num_addresses = m_addresses.size();
8684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    m_break_ids.resize(num_addresses);
8784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
8884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    for (size_t i = 0; i < num_addresses; i++)
8984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    {
9084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        Breakpoint *breakpoint;
9184cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        breakpoint = m_thread.CalculateTarget()->CreateBreakpoint (m_addresses[i], true).get();
9284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        if (breakpoint != NULL)
9384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        {
9484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans            m_break_ids[i] = breakpoint->GetID();
9584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans            breakpoint->SetThreadID(m_thread.GetID());
9684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans            breakpoint->SetBreakpointKind("run-to-address");
9784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        }
9884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    }
9984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans}
10084cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
10184cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::~ThreadPlanRunToAddress ()
10284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
10384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    size_t num_break_ids = m_break_ids.size();
10484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    for (size_t i = 0; i <  num_break_ids; i++)
10584cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    {
10684cbbcb90af44807361198baed4e74ab77715ff7Jason Evans        m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
10784cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    }
10884cbbcb90af44807361198baed4e74ab77715ff7Jason Evans}
10984cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
11084cbbcb90af44807361198baed4e74ab77715ff7Jason Evansvoid
11184cbbcb90af44807361198baed4e74ab77715ff7Jason EvansThreadPlanRunToAddress::GetDescription (Stream *s, lldb::DescriptionLevel level)
11284cbbcb90af44807361198baed4e74ab77715ff7Jason Evans{
11384cbbcb90af44807361198baed4e74ab77715ff7Jason Evans    size_t num_addresses = m_addresses.size();
11484cbbcb90af44807361198baed4e74ab77715ff7Jason Evans
115    if (level == lldb::eDescriptionLevelBrief)
116    {
117        if (num_addresses == 0)
118        {
119            s->Printf ("run to address with no addresses given.");
120            return;
121        }
122        else if (num_addresses == 1)
123            s->Printf ("run to address: ");
124        else
125            s->Printf ("run to addresses: ");
126
127        for (size_t i = 0; i < num_addresses; i++)
128        {
129            s->Address (m_addresses[i], sizeof (addr_t));
130            s->Printf(" ");
131        }
132    }
133    else
134    {
135        if (num_addresses == 0)
136        {
137            s->Printf ("run to address with no addresses given.");
138            return;
139        }
140        else if (num_addresses == 1)
141            s->Printf ("Run to address: ");
142        else
143        {
144            s->Printf ("Run to addresses: ");
145        }
146
147        for (size_t i = 0; i < num_addresses; i++)
148        {
149            if (num_addresses > 1)
150            {
151                s->Printf("\n");
152                s->Indent();
153            }
154
155            s->Address(m_addresses[i], sizeof (addr_t));
156            s->Printf (" using breakpoint: %d - ", m_break_ids[i]);
157            Breakpoint *breakpoint = m_thread.CalculateTarget()->GetBreakpointByID (m_break_ids[i]).get();
158            if (breakpoint)
159                breakpoint->Dump (s);
160            else
161                s->Printf ("but the breakpoint has been deleted.");
162        }
163    }
164}
165
166bool
167ThreadPlanRunToAddress::ValidatePlan (Stream *error)
168{
169    // If we couldn't set the breakpoint for some reason, then this won't
170    // work.
171    bool all_bps_good = true;
172    size_t num_break_ids = m_break_ids.size();
173
174    for (size_t i = 0; i < num_break_ids; i++)
175    {
176        if (m_break_ids[i] == LLDB_INVALID_BREAK_ID)
177        {
178            all_bps_good = false;
179            if (error)
180            {
181                error->Printf ("Could not set breakpoint for address: ");
182                error->Address (m_addresses[i], sizeof (addr_t));
183                error->Printf ("\n");
184            }
185        }
186    }
187    return all_bps_good;
188}
189
190bool
191ThreadPlanRunToAddress::DoPlanExplainsStop (Event *event_ptr)
192{
193    return AtOurAddress();
194}
195
196bool
197ThreadPlanRunToAddress::ShouldStop (Event *event_ptr)
198{
199    return false;
200}
201
202bool
203ThreadPlanRunToAddress::StopOthers ()
204{
205    return m_stop_others;
206}
207
208void
209ThreadPlanRunToAddress::SetStopOthers (bool new_value)
210{
211    m_stop_others = new_value;
212}
213
214StateType
215ThreadPlanRunToAddress::GetPlanRunState ()
216{
217    return eStateRunning;
218}
219
220bool
221ThreadPlanRunToAddress::WillStop ()
222{
223    return true;
224}
225
226bool
227ThreadPlanRunToAddress::MischiefManaged ()
228{
229    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
230
231    if (AtOurAddress())
232    {
233        // Remove the breakpoint
234        size_t num_break_ids = m_break_ids.size();
235
236        for (size_t i = 0; i < num_break_ids; i++)
237        {
238            if (m_break_ids[i] != LLDB_INVALID_BREAK_ID)
239            {
240                m_thread.CalculateTarget()->RemoveBreakpointByID (m_break_ids[i]);
241                m_break_ids[i] = LLDB_INVALID_BREAK_ID;
242            }
243        }
244        if (log)
245            log->Printf("Completed run to address plan.");
246        ThreadPlan::MischiefManaged ();
247        return true;
248    }
249    else
250        return false;
251}
252
253bool
254ThreadPlanRunToAddress::AtOurAddress ()
255{
256    lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
257    bool found_it = false;
258    size_t num_addresses = m_addresses.size();
259    for (size_t i = 0; i < num_addresses; i++)
260    {
261        if (m_addresses[i] == current_address)
262        {
263            found_it = true;
264            break;
265        }
266    }
267    return found_it;
268}
269