Skip to content

Commit f744935

Browse files
authored
Merge pull request #11598 from swiftlang/lldb-dap-backport-before-json
🍒 Backport lldb-dap changes before JSONTransport change
2 parents 0252faa + 4078c20 commit f744935

File tree

55 files changed

+1046
-167
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1046
-167
lines changed

lldb/docs/resources/lldbdap.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,3 +170,26 @@ This is also very simple, just run:
170170
```bash
171171
npm run format
172172
```
173+
174+
## Working with the VS Code extension from another extension
175+
176+
The VS Code extension exposes the following [VS Code
177+
commands](https://code.visualstudio.com/api/extension-guides/command),
178+
which can be invoked by other debugger extensions to leverage this extension's
179+
settings and logic. The commands help resolve configuration, create adapter
180+
descriptor, and get the lldb-dap process for state tracking, additional
181+
interaction, and telemetry.
182+
183+
```
184+
// Resolve debug configuration
185+
const resolvedConfiguration = await vscode.commands.executeCommand("lldb-dap.resolveDebugConfiguration", folder, configuration, token);
186+
187+
// Resolve debug configuration with substituted variables
188+
const resolvedConfigurationWithSubstitutedVariables = await vscode.commands.executeCommand("lldb-dap.resolveDebugConfigurationWithSubstitutedVariables", folder, configuration, token);
189+
190+
// Create debug adapter descriptor
191+
const adapterDescriptor = await vscode.commands.executeCommand("lldb-dap.createDebugAdapterDescriptor", session, executable);
192+
193+
// Get DAP server process
194+
const process = await vscode.commands.executeCommand("lldb-dap.getServerProcess");
195+
```

lldb/include/lldb/API/SBTarget.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -660,6 +660,14 @@ class LLDB_API SBTarget {
660660
lldb::LanguageType symbol_language,
661661
const SBFileSpecList &module_list, const SBFileSpecList &comp_unit_list);
662662

663+
lldb::SBBreakpoint BreakpointCreateByName(
664+
const char *symbol_name,
665+
uint32_t
666+
name_type_mask, // Logical OR one or more FunctionNameType enum bits
667+
lldb::LanguageType symbol_language, lldb::addr_t offset,
668+
bool offset_is_insn_count, const SBFileSpecList &module_list,
669+
const SBFileSpecList &comp_unit_list);
670+
663671
#ifdef SWIG
664672
lldb::SBBreakpoint BreakpointCreateByNames(
665673
const char **symbol_name, uint32_t num_names,

lldb/include/lldb/Breakpoint/BreakpointResolver.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@ class BreakpointResolver : public Searcher {
4545
/// The breakpoint that owns this resolver.
4646
/// \param[in] resolverType
4747
/// The concrete breakpoint resolver type for this breakpoint.
48-
BreakpointResolver(const lldb::BreakpointSP &bkpt,
49-
unsigned char resolverType,
50-
lldb::addr_t offset = 0);
48+
BreakpointResolver(const lldb::BreakpointSP &bkpt, unsigned char resolverType,
49+
lldb::addr_t offset = 0,
50+
bool offset_is_insn_count = false);
5151

5252
/// The Destructor is virtual, all significant breakpoint resolvers derive
5353
/// from this class.
@@ -76,6 +76,7 @@ class BreakpointResolver : public Searcher {
7676
void SetOffset(lldb::addr_t offset);
7777

7878
lldb::addr_t GetOffset() const { return m_offset; }
79+
lldb::addr_t GetOffsetIsInsnCount() const { return m_offset_is_insn_count; }
7980

8081
/// In response to this method the resolver scans all the modules in the
8182
/// breakpoint's target, and adds any new locations it finds.
@@ -220,6 +221,8 @@ class BreakpointResolver : public Searcher {
220221
lldb::BreakpointWP m_breakpoint; // This is the breakpoint we add locations to.
221222
lldb::addr_t m_offset; // A random offset the user asked us to add to any
222223
// breakpoints we set.
224+
bool m_offset_is_insn_count; // Use the offset as an instruction count
225+
// instead of an address offset.
223226

224227
// Subclass identifier (for llvm isa/dyn_cast)
225228
const unsigned char SubclassID;

lldb/include/lldb/Breakpoint/BreakpointResolverName.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class BreakpointResolverName : public BreakpointResolver {
2727
lldb::FunctionNameType name_type_mask,
2828
lldb::LanguageType language,
2929
Breakpoint::MatchType type, lldb::addr_t offset,
30-
bool skip_prologue);
30+
bool offset_is_insn_count, bool skip_prologue);
3131

3232
// This one takes an array of names. It is always MatchType = Exact.
3333
BreakpointResolverName(const lldb::BreakpointSP &bkpt, const char *names[],

lldb/include/lldb/Core/Disassembler.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ class InstructionList {
291291

292292
size_t GetSize() const;
293293

294+
size_t GetTotalByteSize() const;
295+
294296
uint32_t GetMaxOpcocdeByteSize() const;
295297

296298
lldb::InstructionSP GetInstructionAtIndex(size_t idx) const;

lldb/include/lldb/Target/Target.h

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "lldb/Breakpoint/BreakpointList.h"
2020
#include "lldb/Breakpoint/BreakpointName.h"
2121
#include "lldb/Breakpoint/WatchpointList.h"
22+
#include "lldb/Core/Address.h"
2223
#include "lldb/Core/Architecture.h"
2324
#include "lldb/Core/Disassembler.h"
2425
#include "lldb/Core/ModuleList.h"
@@ -817,7 +818,7 @@ class Target : public std::enable_shared_from_this<Target>,
817818
lldb::BreakpointSP CreateBreakpoint(lldb::addr_t load_addr, bool internal,
818819
bool request_hardware);
819820

820-
// Use this to create a breakpoint from a load address and a module file spec
821+
// Use this to create a breakpoint from a file address and a module file spec
821822
lldb::BreakpointSP CreateAddressInModuleBreakpoint(lldb::addr_t file_addr,
822823
bool internal,
823824
const FileSpec &file_spec,
@@ -846,8 +847,8 @@ class Target : public std::enable_shared_from_this<Target>,
846847
const FileSpecList *containingModules,
847848
const FileSpecList *containingSourceFiles, const char *func_name,
848849
lldb::FunctionNameType func_name_type_mask, lldb::LanguageType language,
849-
lldb::addr_t offset, LazyBool skip_prologue, bool internal,
850-
bool request_hardware);
850+
lldb::addr_t offset, bool offset_is_insn_count, LazyBool skip_prologue,
851+
bool internal, bool request_hardware);
851852

852853
lldb::BreakpointSP
853854
CreateExceptionBreakpoint(enum lldb::LanguageType language, bool catch_bp,
@@ -1438,6 +1439,10 @@ class Target : public std::enable_shared_from_this<Target>,
14381439
const lldb_private::RegisterFlags &flags,
14391440
uint32_t byte_size);
14401441

1442+
llvm::Expected<lldb::DisassemblerSP>
1443+
ReadInstructions(const Address &start_addr, uint32_t count,
1444+
const char *flavor_string = nullptr);
1445+
14411446
// Target Stop Hooks
14421447
class StopHook : public UserID {
14431448
public:

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/dap_server.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -107,24 +107,33 @@ def dump_dap_log(log_file):
107107

108108
class Source(object):
109109
def __init__(
110-
self, path: Optional[str] = None, source_reference: Optional[int] = None
110+
self,
111+
path: Optional[str] = None,
112+
source_reference: Optional[int] = None,
113+
raw_dict: Optional[dict[str, Any]] = None,
111114
):
112115
self._name = None
113116
self._path = None
114117
self._source_reference = None
118+
self._raw_dict = None
115119

116120
if path is not None:
117121
self._name = os.path.basename(path)
118122
self._path = path
119123
elif source_reference is not None:
120124
self._source_reference = source_reference
125+
elif raw_dict is not None:
126+
self._raw_dict = raw_dict
121127
else:
122128
raise ValueError("Either path or source_reference must be provided")
123129

124130
def __str__(self):
125131
return f"Source(name={self.name}, path={self.path}), source_reference={self.source_reference})"
126132

127133
def as_dict(self):
134+
if self._raw_dict is not None:
135+
return self._raw_dict
136+
128137
source_dict = {}
129138
if self._name is not None:
130139
source_dict["name"] = self._name
@@ -135,6 +144,19 @@ def as_dict(self):
135144
return source_dict
136145

137146

147+
class Breakpoint(object):
148+
def __init__(self, obj):
149+
self._breakpoint = obj
150+
151+
def is_verified(self):
152+
"""Check if the breakpoint is verified."""
153+
return self._breakpoint.get("verified", False)
154+
155+
def source(self):
156+
"""Get the source of the breakpoint."""
157+
return self._breakpoint.get("source", {})
158+
159+
138160
class NotSupportedError(KeyError):
139161
"""Raised if a feature is not supported due to its capabilities."""
140162

@@ -170,7 +192,7 @@ def __init__(
170192
self.initialized = False
171193
self.frame_scopes = {}
172194
self.init_commands = init_commands
173-
self.resolved_breakpoints = {}
195+
self.resolved_breakpoints: dict[str, Breakpoint] = {}
174196

175197
@classmethod
176198
def encode_content(cls, s: str) -> bytes:
@@ -326,8 +348,8 @@ def _process_continued(self, all_threads_continued: bool):
326348
def _update_verified_breakpoints(self, breakpoints: list[Event]):
327349
for breakpoint in breakpoints:
328350
if "id" in breakpoint:
329-
self.resolved_breakpoints[str(breakpoint["id"])] = breakpoint.get(
330-
"verified", False
351+
self.resolved_breakpoints[str(breakpoint["id"])] = Breakpoint(
352+
breakpoint
331353
)
332354

333355
def send_packet(self, command_dict: Request, set_sequence=True):
@@ -484,7 +506,14 @@ def wait_for_breakpoints_to_be_verified(
484506
if breakpoint_event is None:
485507
break
486508

487-
return [id for id in breakpoint_ids if id not in self.resolved_breakpoints]
509+
return [
510+
id
511+
for id in breakpoint_ids
512+
if (
513+
id not in self.resolved_breakpoints
514+
or not self.resolved_breakpoints[id].is_verified()
515+
)
516+
]
488517

489518
def wait_for_exited(self, timeout: Optional[float] = None):
490519
event_dict = self.wait_for_event("exited", timeout=timeout)

lldb/packages/Python/lldbsuite/test/tools/lldb-dap/lldbdap_testcase.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -59,24 +59,22 @@ def set_source_breakpoints(
5959
Each object in data is 1:1 mapping with the entry in lines.
6060
It contains optional location/hitCondition/logMessage parameters.
6161
"""
62-
response = self.dap_server.request_setBreakpoints(
63-
Source(source_path), lines, data
62+
return self.set_source_breakpoints_from_source(
63+
Source(path=source_path), lines, data, wait_for_resolve
6464
)
65-
if response is None or not response["success"]:
66-
return []
67-
breakpoints = response["body"]["breakpoints"]
68-
breakpoint_ids = []
69-
for breakpoint in breakpoints:
70-
breakpoint_ids.append("%i" % (breakpoint["id"]))
71-
if wait_for_resolve:
72-
self.wait_for_breakpoints_to_resolve(breakpoint_ids)
73-
return breakpoint_ids
7465

7566
def set_source_breakpoints_assembly(
7667
self, source_reference, lines, data=None, wait_for_resolve=True
68+
):
69+
return self.set_source_breakpoints_from_source(
70+
Source(source_reference=source_reference), lines, data, wait_for_resolve
71+
)
72+
73+
def set_source_breakpoints_from_source(
74+
self, source: Source, lines, data=None, wait_for_resolve=True
7775
):
7876
response = self.dap_server.request_setBreakpoints(
79-
Source(source_reference=source_reference),
77+
source,
8078
lines,
8179
data,
8280
)
@@ -173,6 +171,28 @@ def verify_breakpoint_hit(self, breakpoint_ids, timeout=DEFAULT_TIMEOUT):
173171
return
174172
self.assertTrue(False, f"breakpoint not hit, stopped_events={stopped_events}")
175173

174+
def verify_all_breakpoints_hit(self, breakpoint_ids, timeout=DEFAULT_TIMEOUT):
175+
"""Wait for the process we are debugging to stop, and verify we hit
176+
all of the breakpoint locations in the "breakpoint_ids" array.
177+
"breakpoint_ids" should be a list of int breakpoint IDs ([1, 2])."""
178+
stopped_events = self.dap_server.wait_for_stopped(timeout)
179+
for stopped_event in stopped_events:
180+
if "body" in stopped_event:
181+
body = stopped_event["body"]
182+
if "reason" not in body:
183+
continue
184+
if (
185+
body["reason"] != "breakpoint"
186+
and body["reason"] != "instruction breakpoint"
187+
):
188+
continue
189+
if "hitBreakpointIds" not in body:
190+
continue
191+
hit_bps = body["hitBreakpointIds"]
192+
if all(breakpoint_id in hit_bps for breakpoint_id in breakpoint_ids):
193+
return
194+
self.assertTrue(False, f"breakpoints not hit, stopped_events={stopped_events}")
195+
176196
def verify_stop_exception_info(self, expected_description, timeout=DEFAULT_TIMEOUT):
177197
"""Wait for the process we are debugging to stop, and verify the stop
178198
reason is 'exception' and that the description matches

lldb/source/API/SBTarget.cpp

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -771,16 +771,19 @@ SBBreakpoint SBTarget::BreakpointCreateByName(const char *symbol_name,
771771
const bool hardware = false;
772772
const LazyBool skip_prologue = eLazyBoolCalculate;
773773
const lldb::addr_t offset = 0;
774+
const bool offset_is_insn_count = false;
774775
if (module_name && module_name[0]) {
775776
FileSpecList module_spec_list;
776777
module_spec_list.Append(FileSpec(module_name));
777778
sb_bp = target_sp->CreateBreakpoint(
778779
&module_spec_list, nullptr, symbol_name, eFunctionNameTypeAuto,
779-
eLanguageTypeUnknown, offset, skip_prologue, internal, hardware);
780+
eLanguageTypeUnknown, offset, offset_is_insn_count, skip_prologue,
781+
internal, hardware);
780782
} else {
781783
sb_bp = target_sp->CreateBreakpoint(
782784
nullptr, nullptr, symbol_name, eFunctionNameTypeAuto,
783-
eLanguageTypeUnknown, offset, skip_prologue, internal, hardware);
785+
eLanguageTypeUnknown, offset, offset_is_insn_count, skip_prologue,
786+
internal, hardware);
784787
}
785788
}
786789

@@ -816,6 +819,17 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
816819
const SBFileSpecList &comp_unit_list) {
817820
LLDB_INSTRUMENT_VA(this, symbol_name, name_type_mask, symbol_language,
818821
module_list, comp_unit_list);
822+
return BreakpointCreateByName(symbol_name, name_type_mask, symbol_language, 0,
823+
false, module_list, comp_unit_list);
824+
}
825+
826+
lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
827+
const char *symbol_name, uint32_t name_type_mask,
828+
LanguageType symbol_language, lldb::addr_t offset,
829+
bool offset_is_insn_count, const SBFileSpecList &module_list,
830+
const SBFileSpecList &comp_unit_list) {
831+
LLDB_INSTRUMENT_VA(this, symbol_name, name_type_mask, symbol_language, offset,
832+
offset_is_insn_count, module_list, comp_unit_list);
819833

820834
SBBreakpoint sb_bp;
821835
if (TargetSP target_sp = GetSP();
@@ -826,7 +840,8 @@ lldb::SBBreakpoint SBTarget::BreakpointCreateByName(
826840
std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
827841
FunctionNameType mask = static_cast<FunctionNameType>(name_type_mask);
828842
sb_bp = target_sp->CreateBreakpoint(module_list.get(), comp_unit_list.get(),
829-
symbol_name, mask, symbol_language, 0,
843+
symbol_name, mask, symbol_language,
844+
offset, offset_is_insn_count,
830845
skip_prologue, internal, hardware);
831846
}
832847

@@ -2013,29 +2028,10 @@ lldb::SBInstructionList SBTarget::ReadInstructions(lldb::SBAddress base_addr,
20132028

20142029
if (TargetSP target_sp = GetSP()) {
20152030
if (Address *addr_ptr = base_addr.get()) {
2016-
DataBufferHeap data(
2017-
target_sp->GetArchitecture().GetMaximumOpcodeByteSize() * count, 0);
2018-
bool force_live_memory = true;
2019-
lldb_private::Status error;
2020-
lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
2021-
const size_t bytes_read =
2022-
target_sp->ReadMemory(*addr_ptr, data.GetBytes(), data.GetByteSize(),
2023-
error, force_live_memory, &load_addr);
2024-
2025-
const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
2026-
if (!flavor_string || flavor_string[0] == '\0') {
2027-
// FIXME - we don't have the mechanism in place to do per-architecture
2028-
// settings. But since we know that for now we only support flavors on
2029-
// x86 & x86_64,
2030-
const llvm::Triple::ArchType arch =
2031-
target_sp->GetArchitecture().GetTriple().getArch();
2032-
if (arch == llvm::Triple::x86 || arch == llvm::Triple::x86_64)
2033-
flavor_string = target_sp->GetDisassemblyFlavor();
2031+
if (llvm::Expected<DisassemblerSP> disassembler =
2032+
target_sp->ReadInstructions(*addr_ptr, count, flavor_string)) {
2033+
sb_instructions.SetDisassembler(*disassembler);
20342034
}
2035-
sb_instructions.SetDisassembler(Disassembler::DisassembleBytes(
2036-
target_sp->GetArchitecture(), nullptr, flavor_string,
2037-
target_sp->GetDisassemblyCPU(), target_sp->GetDisassemblyFeatures(),
2038-
*addr_ptr, data.GetBytes(), bytes_read, count, data_from_file));
20392035
}
20402036
}
20412037

0 commit comments

Comments
 (0)