ThreadPlanRunToAddress.cpp revision 360784
1//===-- ThreadPlanRunToAddress.cpp ------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "lldb/Target/ThreadPlanRunToAddress.h"
10#include "lldb/Target/Process.h"
11#include "lldb/Target/RegisterContext.h"
12#include "lldb/Target/Target.h"
13#include "lldb/Target/Thread.h"
14#include "lldb/Utility/Log.h"
15#include "lldb/Utility/Stream.h"
16
17using namespace lldb;
18using namespace lldb_private;
19
20// ThreadPlanRunToAddress: Continue plan
21
22ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,
23                                               bool stop_others)
24    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
25                 eVoteNoOpinion, eVoteNoOpinion),
26      m_stop_others(stop_others), m_addresses(), m_break_ids() {
27  m_addresses.push_back(
28      address.GetOpcodeLoadAddress(m_thread.CalculateTarget().get()));
29  SetInitialBreakpoints();
30}
31
32ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,
33                                               lldb::addr_t address,
34                                               bool stop_others)
35    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
36                 eVoteNoOpinion, eVoteNoOpinion),
37      m_stop_others(stop_others), m_addresses(), m_break_ids() {
38  m_addresses.push_back(
39      m_thread.CalculateTarget()->GetOpcodeLoadAddress(address));
40  SetInitialBreakpoints();
41}
42
43ThreadPlanRunToAddress::ThreadPlanRunToAddress(
44    Thread &thread, const std::vector<lldb::addr_t> &addresses,
45    bool stop_others)
46    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,
47                 eVoteNoOpinion, eVoteNoOpinion),
48      m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {
49  // Convert all addresses into opcode addresses to make sure we set
50  // breakpoints at the correct address.
51  Target &target = thread.GetProcess()->GetTarget();
52  std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();
53  for (pos = m_addresses.begin(); pos != end; ++pos)
54    *pos = target.GetOpcodeLoadAddress(*pos);
55
56  SetInitialBreakpoints();
57}
58
59void ThreadPlanRunToAddress::SetInitialBreakpoints() {
60  size_t num_addresses = m_addresses.size();
61  m_break_ids.resize(num_addresses);
62
63  for (size_t i = 0; i < num_addresses; i++) {
64    Breakpoint *breakpoint;
65    breakpoint = m_thread.CalculateTarget()
66                     ->CreateBreakpoint(m_addresses[i], true, false)
67                     .get();
68    if (breakpoint != nullptr) {
69      if (breakpoint->IsHardware() && !breakpoint->HasResolvedLocations())
70        m_could_not_resolve_hw_bp = true;
71      m_break_ids[i] = breakpoint->GetID();
72      breakpoint->SetThreadID(m_thread.GetID());
73      breakpoint->SetBreakpointKind("run-to-address");
74    }
75  }
76}
77
78ThreadPlanRunToAddress::~ThreadPlanRunToAddress() {
79  size_t num_break_ids = m_break_ids.size();
80  for (size_t i = 0; i < num_break_ids; i++) {
81    m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
82  }
83  m_could_not_resolve_hw_bp = false;
84}
85
86void ThreadPlanRunToAddress::GetDescription(Stream *s,
87                                            lldb::DescriptionLevel level) {
88  size_t num_addresses = m_addresses.size();
89
90  if (level == lldb::eDescriptionLevelBrief) {
91    if (num_addresses == 0) {
92      s->Printf("run to address with no addresses given.");
93      return;
94    } else if (num_addresses == 1)
95      s->Printf("run to address: ");
96    else
97      s->Printf("run to addresses: ");
98
99    for (size_t i = 0; i < num_addresses; i++) {
100      DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
101      s->Printf(" ");
102    }
103  } else {
104    if (num_addresses == 0) {
105      s->Printf("run to address with no addresses given.");
106      return;
107    } else if (num_addresses == 1)
108      s->Printf("Run to address: ");
109    else {
110      s->Printf("Run to addresses: ");
111    }
112
113    for (size_t i = 0; i < num_addresses; i++) {
114      if (num_addresses > 1) {
115        s->Printf("\n");
116        s->Indent();
117      }
118
119      DumpAddress(s->AsRawOstream(), m_addresses[i], sizeof(addr_t));
120      s->Printf(" using breakpoint: %d - ", m_break_ids[i]);
121      Breakpoint *breakpoint =
122          m_thread.CalculateTarget()->GetBreakpointByID(m_break_ids[i]).get();
123      if (breakpoint)
124        breakpoint->Dump(s);
125      else
126        s->Printf("but the breakpoint has been deleted.");
127    }
128  }
129}
130
131bool ThreadPlanRunToAddress::ValidatePlan(Stream *error) {
132  if (m_could_not_resolve_hw_bp) {
133    if (error)
134      error->Printf("Could not set hardware breakpoint(s)");
135    return false;
136  }
137
138  // If we couldn't set the breakpoint for some reason, then this won't work.
139  bool all_bps_good = true;
140  size_t num_break_ids = m_break_ids.size();
141  for (size_t i = 0; i < num_break_ids; i++) {
142    if (m_break_ids[i] == LLDB_INVALID_BREAK_ID) {
143      all_bps_good = false;
144      if (error) {
145        error->Printf("Could not set breakpoint for address: ");
146        DumpAddress(error->AsRawOstream(), m_addresses[i], sizeof(addr_t));
147        error->Printf("\n");
148      }
149    }
150  }
151  return all_bps_good;
152}
153
154bool ThreadPlanRunToAddress::DoPlanExplainsStop(Event *event_ptr) {
155  return AtOurAddress();
156}
157
158bool ThreadPlanRunToAddress::ShouldStop(Event *event_ptr) {
159  return AtOurAddress();
160}
161
162bool ThreadPlanRunToAddress::StopOthers() { return m_stop_others; }
163
164void ThreadPlanRunToAddress::SetStopOthers(bool new_value) {
165  m_stop_others = new_value;
166}
167
168StateType ThreadPlanRunToAddress::GetPlanRunState() { return eStateRunning; }
169
170bool ThreadPlanRunToAddress::WillStop() { return true; }
171
172bool ThreadPlanRunToAddress::MischiefManaged() {
173  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
174
175  if (AtOurAddress()) {
176    // Remove the breakpoint
177    size_t num_break_ids = m_break_ids.size();
178
179    for (size_t i = 0; i < num_break_ids; i++) {
180      if (m_break_ids[i] != LLDB_INVALID_BREAK_ID) {
181        m_thread.CalculateTarget()->RemoveBreakpointByID(m_break_ids[i]);
182        m_break_ids[i] = LLDB_INVALID_BREAK_ID;
183      }
184    }
185    LLDB_LOGF(log, "Completed run to address plan.");
186    ThreadPlan::MischiefManaged();
187    return true;
188  } else
189    return false;
190}
191
192bool ThreadPlanRunToAddress::AtOurAddress() {
193  lldb::addr_t current_address = m_thread.GetRegisterContext()->GetPC();
194  bool found_it = false;
195  size_t num_addresses = m_addresses.size();
196  for (size_t i = 0; i < num_addresses; i++) {
197    if (m_addresses[i] == current_address) {
198      found_it = true;
199      break;
200    }
201  }
202  return found_it;
203}
204