brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · a2ac8c3 Raw
204 lines · cpp
1//===-- ThreadPlanRunToAddress.cpp ----------------------------------------===//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-exception6//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/LLDBLog.h"15#include "lldb/Utility/Log.h"16#include "lldb/Utility/Stream.h"17 18using namespace lldb;19using namespace lldb_private;20 21// ThreadPlanRunToAddress: Continue plan22 23ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread, Address &address,24                                               bool stop_others)25    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,26                 eVoteNoOpinion, eVoteNoOpinion),27      m_stop_others(stop_others), m_addresses(), m_break_ids() {28  m_addresses.push_back(29      address.GetOpcodeLoadAddress(thread.CalculateTarget().get()));30  SetInitialBreakpoints();31}32 33ThreadPlanRunToAddress::ThreadPlanRunToAddress(Thread &thread,34                                               lldb::addr_t address,35                                               bool stop_others)36    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,37                 eVoteNoOpinion, eVoteNoOpinion),38      m_stop_others(stop_others), m_addresses(), m_break_ids() {39  m_addresses.push_back(40      thread.CalculateTarget()->GetOpcodeLoadAddress(address));41  SetInitialBreakpoints();42}43 44ThreadPlanRunToAddress::ThreadPlanRunToAddress(45    Thread &thread, const std::vector<lldb::addr_t> &addresses,46    bool stop_others)47    : ThreadPlan(ThreadPlan::eKindRunToAddress, "Run to address plan", thread,48                 eVoteNoOpinion, eVoteNoOpinion),49      m_stop_others(stop_others), m_addresses(addresses), m_break_ids() {50  // Convert all addresses into opcode addresses to make sure we set51  // breakpoints at the correct address.52  Target &target = thread.GetProcess()->GetTarget();53  std::vector<lldb::addr_t>::iterator pos, end = m_addresses.end();54  for (pos = m_addresses.begin(); pos != end; ++pos)55    *pos = target.GetOpcodeLoadAddress(*pos);56 57  SetInitialBreakpoints();58}59 60void ThreadPlanRunToAddress::SetInitialBreakpoints() {61  size_t num_addresses = m_addresses.size();62  m_break_ids.resize(num_addresses);63 64  for (size_t i = 0; i < num_addresses; i++) {65    Breakpoint *breakpoint;66    breakpoint =67        GetTarget().CreateBreakpoint(m_addresses[i], true, false).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_tid);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    GetTarget().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    else97      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          GetTarget().GetBreakpointByID(m_break_ids[i]).get();123      if (breakpoint)124        breakpoint->Dump(s);125      else126        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 = GetLog(LLDBLog::Step);174 175  if (AtOurAddress()) {176    // Remove the breakpoint177    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        GetTarget().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  } else189    return false;190}191 192bool ThreadPlanRunToAddress::AtOurAddress() {193  lldb::addr_t current_address = GetThread().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