brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.5 KiB · c803957 Raw
137 lines · cpp
1//===-- Breakpoint.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 "Breakpoint.h"10#include "DAP.h"11#include "LLDBUtils.h"12#include "Protocol/DAPTypes.h"13#include "ProtocolUtils.h"14#include "lldb/API/SBAddress.h"15#include "lldb/API/SBBreakpointLocation.h"16#include "lldb/API/SBFileSpec.h"17#include "lldb/API/SBLineEntry.h"18#include "lldb/API/SBModule.h"19#include "lldb/API/SBMutex.h"20#include "llvm/ADT/StringExtras.h"21#include <cstddef>22#include <cstdint>23#include <mutex>24#include <string>25 26using namespace lldb_dap;27 28static std::optional<protocol::PersistenceData>29GetPersistenceDataForSymbol(lldb::SBSymbol &symbol) {30  protocol::PersistenceData persistence_data;31  lldb::SBModule module = symbol.GetStartAddress().GetModule();32  if (!module.IsValid())33    return std::nullopt;34 35  lldb::SBFileSpec file_spec = module.GetFileSpec();36  if (!file_spec.IsValid())37    return std::nullopt;38 39  persistence_data.module_path = GetSBFileSpecPath(file_spec);40  persistence_data.symbol_name = symbol.GetName();41  return persistence_data;42}43 44void Breakpoint::SetCondition() { m_bp.SetCondition(m_condition.c_str()); }45 46void Breakpoint::SetHitCondition() {47  uint64_t hitCount = 0;48  if (llvm::to_integer(m_hit_condition, hitCount))49    m_bp.SetIgnoreCount(hitCount - 1);50}51 52protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() {53  protocol::Breakpoint breakpoint;54 55  // Each breakpoint location is treated as a separate breakpoint for VS code.56  // They don't have the notion of a single breakpoint with multiple locations.57  if (!m_bp.IsValid())58    return breakpoint;59 60  breakpoint.verified = m_bp.GetNumResolvedLocations() > 0;61  breakpoint.id = m_bp.GetID();62  // VS Code DAP doesn't currently allow one breakpoint to have multiple63  // locations so we just report the first one. If we report all locations64  // then the IDE starts showing the wrong line numbers and locations for65  // other source file and line breakpoints in the same file.66 67  // Below we search for the first resolved location in a breakpoint and report68  // this as the breakpoint location since it will have a complete location69  // that is at least loaded in the current process.70  lldb::SBBreakpointLocation bp_loc;71  const auto num_locs = m_bp.GetNumLocations();72  for (size_t i = 0; i < num_locs; ++i) {73    bp_loc = m_bp.GetLocationAtIndex(i);74    if (bp_loc.IsResolved())75      break;76  }77  // If not locations are resolved, use the first location.78  if (!bp_loc.IsResolved())79    bp_loc = m_bp.GetLocationAtIndex(0);80  auto bp_addr = bp_loc.GetAddress();81 82  if (bp_addr.IsValid()) {83    std::string formatted_addr =84        "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(m_bp.GetTarget()));85    breakpoint.instructionReference = formatted_addr;86 87    std::optional<protocol::Source> source = m_dap.ResolveSource(bp_addr);88    if (source && !IsAssemblySource(*source)) {89      auto line_entry = bp_addr.GetLineEntry();90      const auto line = line_entry.GetLine();91      if (line != LLDB_INVALID_LINE_NUMBER)92        breakpoint.line = line;93      const auto column = line_entry.GetColumn();94      if (column != LLDB_INVALID_COLUMN_NUMBER)95        breakpoint.column = column;96    } else if (source) {97      // Assembly breakpoint.98      auto symbol = bp_addr.GetSymbol();99      if (symbol.IsValid()) {100        breakpoint.line =101            m_bp.GetTarget()102                .ReadInstructions(symbol.GetStartAddress(), bp_addr, nullptr)103                .GetSize() +104            1;105 106        // Add persistent data so that the breakpoint can be resolved107        // in future sessions.108        std::optional<protocol::PersistenceData> persistence_data =109            GetPersistenceDataForSymbol(symbol);110        if (persistence_data) {111          source->adapterData =112              protocol::SourceLLDBData{std::move(persistence_data)};113        }114      }115    }116 117    breakpoint.source = std::move(source);118  }119 120  return breakpoint;121}122 123bool Breakpoint::MatchesName(const char *name) {124  return m_bp.MatchesName(name);125}126 127void Breakpoint::SetBreakpoint() {128  lldb::SBMutex lock = m_dap.GetAPIMutex();129  std::lock_guard<lldb::SBMutex> guard(lock);130 131  m_bp.AddName(kDAPBreakpointLabel);132  if (!m_condition.empty())133    SetCondition();134  if (!m_hit_condition.empty())135    SetHitCondition();136}137