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