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 "JSONUtils.h" 11 #include "lldb/API/SBAddress.h" 12 #include "lldb/API/SBBreakpointLocation.h" 13 #include "lldb/API/SBLineEntry.h" 14 #include "llvm/ADT/StringExtras.h" 15 #include "llvm/Support/JSON.h" 16 #include <cstddef> 17 #include <cstdint> 18 #include <string> 19 20 using namespace lldb_dap; 21 22 void Breakpoint::SetCondition() { bp.SetCondition(condition.c_str()); } 23 24 void Breakpoint::SetHitCondition() { 25 uint64_t hitCount = 0; 26 if (llvm::to_integer(hitCondition, hitCount)) 27 bp.SetIgnoreCount(hitCount - 1); 28 } 29 30 void Breakpoint::CreateJsonObject(llvm::json::Object &object) { 31 // Each breakpoint location is treated as a separate breakpoint for VS code. 32 // They don't have the notion of a single breakpoint with multiple locations. 33 if (!bp.IsValid()) 34 return; 35 object.try_emplace("verified", bp.GetNumResolvedLocations() > 0); 36 object.try_emplace("id", bp.GetID()); 37 // VS Code DAP doesn't currently allow one breakpoint to have multiple 38 // locations so we just report the first one. If we report all locations 39 // then the IDE starts showing the wrong line numbers and locations for 40 // other source file and line breakpoints in the same file. 41 42 // Below we search for the first resolved location in a breakpoint and report 43 // this as the breakpoint location since it will have a complete location 44 // that is at least loaded in the current process. 45 lldb::SBBreakpointLocation bp_loc; 46 const auto num_locs = bp.GetNumLocations(); 47 for (size_t i = 0; i < num_locs; ++i) { 48 bp_loc = bp.GetLocationAtIndex(i); 49 if (bp_loc.IsResolved()) 50 break; 51 } 52 // If not locations are resolved, use the first location. 53 if (!bp_loc.IsResolved()) 54 bp_loc = bp.GetLocationAtIndex(0); 55 auto bp_addr = bp_loc.GetAddress(); 56 57 if (bp_addr.IsValid()) { 58 std::string formatted_addr = 59 "0x" + llvm::utohexstr(bp_addr.GetLoadAddress(bp.GetTarget())); 60 object.try_emplace("instructionReference", formatted_addr); 61 auto line_entry = bp_addr.GetLineEntry(); 62 const auto line = line_entry.GetLine(); 63 if (line != UINT32_MAX) 64 object.try_emplace("line", line); 65 const auto column = line_entry.GetColumn(); 66 if (column != 0) 67 object.try_emplace("column", column); 68 object.try_emplace("source", CreateSource(line_entry)); 69 } 70 } 71 72 bool Breakpoint::MatchesName(const char *name) { return bp.MatchesName(name); } 73 74 void Breakpoint::SetBreakpoint() { 75 // See comments in BreakpointBase::GetBreakpointLabel() for details of why 76 // we add a label to our breakpoints. 77 bp.AddName(GetBreakpointLabel()); 78 if (!condition.empty()) 79 SetCondition(); 80 if (!hitCondition.empty()) 81 SetHitCondition(); 82 } 83