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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Breakpoint.h"
10#include "DAP.h"
11#include "ProtocolUtils.h"
12#include "lldb/API/SBAddress.h"
13#include "lldb/API/SBBreakpointLocation.h"
14#include "lldb/API/SBLineEntry.h"
15#include "lldb/API/SBMutex.h"
16#include "llvm/ADT/StringExtras.h"
17#include <cstddef>
18#include <cstdint>
19#include <mutex>
20#include <string>
21
22using namespace lldb_dap;
23
24void Breakpoint::SetCondition() { m_bp.SetCondition(m_condition.c_str()); }
25
26void Breakpoint::SetHitCondition() {
27 uint64_t hitCount = 0;
28 if (llvm::to_integer(S: m_hit_condition, Num&: hitCount))
29 m_bp.SetIgnoreCount(hitCount - 1);
30}
31
32protocol::Breakpoint Breakpoint::ToProtocolBreakpoint() {
33 protocol::Breakpoint breakpoint;
34
35 // Each breakpoint location is treated as a separate breakpoint for VS code.
36 // They don't have the notion of a single breakpoint with multiple locations.
37 if (!m_bp.IsValid())
38 return breakpoint;
39
40 breakpoint.verified = m_bp.GetNumResolvedLocations() > 0;
41 breakpoint.id = m_bp.GetID();
42 // VS Code DAP doesn't currently allow one breakpoint to have multiple
43 // locations so we just report the first one. If we report all locations
44 // then the IDE starts showing the wrong line numbers and locations for
45 // other source file and line breakpoints in the same file.
46
47 // Below we search for the first resolved location in a breakpoint and report
48 // this as the breakpoint location since it will have a complete location
49 // that is at least loaded in the current process.
50 lldb::SBBreakpointLocation bp_loc;
51 const auto num_locs = m_bp.GetNumLocations();
52 for (size_t i = 0; i < num_locs; ++i) {
53 bp_loc = m_bp.GetLocationAtIndex(index: i);
54 if (bp_loc.IsResolved())
55 break;
56 }
57 // If not locations are resolved, use the first location.
58 if (!bp_loc.IsResolved())
59 bp_loc = m_bp.GetLocationAtIndex(index: 0);
60 auto bp_addr = bp_loc.GetAddress();
61
62 if (bp_addr.IsValid()) {
63 std::string formatted_addr =
64 "0x" + llvm::utohexstr(X: bp_addr.GetLoadAddress(target: m_bp.GetTarget()));
65 breakpoint.instructionReference = formatted_addr;
66
67 auto source = CreateSource(address: bp_addr, target&: m_dap.target);
68 if (!IsAssemblySource(source)) {
69 auto line_entry = bp_addr.GetLineEntry();
70 const auto line = line_entry.GetLine();
71 if (line != LLDB_INVALID_LINE_NUMBER)
72 breakpoint.line = line;
73 const auto column = line_entry.GetColumn();
74 if (column != LLDB_INVALID_COLUMN_NUMBER)
75 breakpoint.column = column;
76 } else {
77 // Assembly breakpoint.
78 auto symbol = bp_addr.GetSymbol();
79 if (symbol.IsValid()) {
80 breakpoint.line =
81 m_bp.GetTarget()
82 .ReadInstructions(start_addr: symbol.GetStartAddress(), end_addr: bp_addr, flavor_string: nullptr)
83 .GetSize() +
84 1;
85 }
86 }
87
88 breakpoint.source = std::move(source);
89 }
90
91 return breakpoint;
92}
93
94bool Breakpoint::MatchesName(const char *name) {
95 return m_bp.MatchesName(name);
96}
97
98void Breakpoint::SetBreakpoint() {
99 lldb::SBMutex lock = m_dap.GetAPIMutex();
100 std::lock_guard<lldb::SBMutex> guard(lock);
101
102 m_bp.AddName(new_name: kDAPBreakpointLabel);
103 if (!m_condition.empty())
104 SetCondition();
105 if (!m_hit_condition.empty())
106 SetHitCondition();
107}
108

source code of lldb/tools/lldb-dap/Breakpoint.cpp