88
99#include " DAP.h"
1010#include " EventHelper.h"
11- #include " JSONUtils .h"
11+ #include " Protocol/ProtocolTypes .h"
1212#include " RequestHandler.h"
1313#include " lldb/API/SBMemoryRegionInfo.h"
1414#include " llvm/ADT/StringExtras.h"
15+ #include < optional>
1516
1617namespace lldb_dap {
1718
18- // "DataBreakpointInfoRequest": {
19- // "allOf": [ { "$ref": "#/definitions/Request" }, {
20- // "type": "object",
21- // "description": "Obtains information on a possible data breakpoint that
22- // could be set on an expression or variable.\nClients should only call this
23- // request if the corresponding capability `supportsDataBreakpoints` is
24- // true.", "properties": {
25- // "command": {
26- // "type": "string",
27- // "enum": [ "dataBreakpointInfo" ]
28- // },
29- // "arguments": {
30- // "$ref": "#/definitions/DataBreakpointInfoArguments"
31- // }
32- // },
33- // "required": [ "command", "arguments" ]
34- // }]
35- // },
36- // "DataBreakpointInfoArguments": {
37- // "type": "object",
38- // "description": "Arguments for `dataBreakpointInfo` request.",
39- // "properties": {
40- // "variablesReference": {
41- // "type": "integer",
42- // "description": "Reference to the variable container if the data
43- // breakpoint is requested for a child of the container. The
44- // `variablesReference` must have been obtained in the current suspended
45- // state. See 'Lifetime of Object References' in the Overview section for
46- // details."
47- // },
48- // "name": {
49- // "type": "string",
50- // "description": "The name of the variable's child to obtain data
51- // breakpoint information for.\nIf `variablesReference` isn't specified,
52- // this can be an expression."
53- // },
54- // "frameId": {
55- // "type": "integer",
56- // "description": "When `name` is an expression, evaluate it in the scope
57- // of this stack frame. If not specified, the expression is evaluated in
58- // the global scope. When `variablesReference` is specified, this property
59- // has no effect."
60- // }
61- // },
62- // "required": [ "name" ]
63- // },
64- // "DataBreakpointInfoResponse": {
65- // "allOf": [ { "$ref": "#/definitions/Response" }, {
66- // "type": "object",
67- // "description": "Response to `dataBreakpointInfo` request.",
68- // "properties": {
69- // "body": {
70- // "type": "object",
71- // "properties": {
72- // "dataId": {
73- // "type": [ "string", "null" ],
74- // "description": "An identifier for the data on which a data
75- // breakpoint can be registered with the `setDataBreakpoints`
76- // request or null if no data breakpoint is available. If a
77- // `variablesReference` or `frameId` is passed, the `dataId` is
78- // valid in the current suspended state, otherwise it's valid
79- // indefinitely. See 'Lifetime of Object References' in the Overview
80- // section for details. Breakpoints set using the `dataId` in the
81- // `setDataBreakpoints` request may outlive the lifetime of the
82- // associated `dataId`."
83- // },
84- // "description": {
85- // "type": "string",
86- // "description": "UI string that describes on what data the
87- // breakpoint is set on or why a data breakpoint is not available."
88- // },
89- // "accessTypes": {
90- // "type": "array",
91- // "items": {
92- // "$ref": "#/definitions/DataBreakpointAccessType"
93- // },
94- // "description": "Attribute lists the available access types for a
95- // potential data breakpoint. A UI client could surface this
96- // information."
97- // },
98- // "canPersist": {
99- // "type": "boolean",
100- // "description": "Attribute indicates that a potential data
101- // breakpoint could be persisted across sessions."
102- // }
103- // },
104- // "required": [ "dataId", "description" ]
105- // }
106- // },
107- // "required": [ "body" ]
108- // }]
109- // }
110- void DataBreakpointInfoRequestHandler::operator ()(
111- const llvm::json::Object &request) const {
112- llvm::json::Object response;
113- FillResponse (request, response);
114- llvm::json::Object body;
115- lldb::SBError error;
116- llvm::json::Array accessTypes{" read" , " write" , " readWrite" };
117- const auto *arguments = request.getObject (" arguments" );
118- const auto variablesReference =
119- GetInteger<uint64_t >(arguments, " variablesReference" ).value_or (0 );
120- llvm::StringRef name = GetString (arguments, " name" ).value_or (" " );
121- lldb::SBFrame frame = dap.GetLLDBFrame (*arguments);
122- lldb::SBValue variable = dap.variables .FindVariable (variablesReference, name);
19+ // / Obtains information on a possible data breakpoint that could be set on an
20+ // / expression or variable. Clients should only call this request if the
21+ // / corresponding capability supportsDataBreakpoints is true.
22+ llvm::Expected<protocol::DataBreakpointInfoResponseBody>
23+ DataBreakpointInfoRequestHandler::Run (
24+ const protocol::DataBreakpointInfoArguments &args) const {
25+ protocol::DataBreakpointInfoResponseBody response;
26+ lldb::SBFrame frame = dap.GetLLDBFrame (args.frameId );
27+ lldb::SBValue variable = dap.variables .FindVariable (
28+ args.variablesReference .value_or (0 ), args.name );
12329 std::string addr, size;
12430
12531 if (variable.IsValid ()) {
12632 lldb::addr_t load_addr = variable.GetLoadAddress ();
12733 size_t byte_size = variable.GetByteSize ();
12834 if (load_addr == LLDB_INVALID_ADDRESS) {
129- body.try_emplace (" dataId" , nullptr );
130- body.try_emplace (" description" ,
131- " does not exist in memory, its location is " +
132- std::string (variable.GetLocation ()));
35+ response.dataId = std::nullopt ;
36+ response.description = " does not exist in memory, its location is " +
37+ std::string (variable.GetLocation ());
13338 } else if (byte_size == 0 ) {
134- body. try_emplace ( " dataId" , nullptr ) ;
135- body. try_emplace ( " description" , " variable size is 0" ) ;
39+ response. dataId = std:: nullopt ;
40+ response. description = " variable size is 0" ;
13641 } else {
13742 addr = llvm::utohexstr (load_addr);
13843 size = llvm::utostr (byte_size);
13944 }
140- } else if (variablesReference == 0 && frame.IsValid ()) {
141- lldb::SBValue value = frame.EvaluateExpression (name.data ());
45+ } else if (args. variablesReference . value_or ( 0 ) == 0 && frame.IsValid ()) {
46+ lldb::SBValue value = frame.EvaluateExpression (args. name .c_str ());
14247 if (value.GetError ().Fail ()) {
14348 lldb::SBError error = value.GetError ();
14449 const char *error_cstr = error.GetCString ();
145- body. try_emplace ( " dataId" , nullptr ) ;
146- body. try_emplace ( " description" , error_cstr && error_cstr[0 ]
147- ? std::string (error_cstr)
148- : " evaluation failed" ) ;
50+ response. dataId = std:: nullopt ;
51+ response. description = error_cstr && error_cstr[0 ]
52+ ? std::string (error_cstr)
53+ : " evaluation failed" ;
14954 } else {
15055 uint64_t load_addr = value.GetValueAsUnsigned ();
15156 lldb::SBData data = value.GetPointeeData ();
@@ -159,32 +64,31 @@ void DataBreakpointInfoRequestHandler::operator()(
15964 // request if SBProcess::GetMemoryRegionInfo returns error.
16065 if (err.Success ()) {
16166 if (!(region.IsReadable () || region.IsWritable ())) {
162- body.try_emplace (" dataId" , nullptr );
163- body.try_emplace (" description" ,
164- " memory region for address " + addr +
165- " has no read or write permissions" );
67+ response.dataId = std::nullopt ;
68+ response.description = " memory region for address " + addr +
69+ " has no read or write permissions" ;
16670 }
16771 }
16872 } else {
169- body.try_emplace (" dataId" , nullptr );
170- body.try_emplace (" description" ,
171- " unable to get byte size for expression: " +
172- name.str ());
73+ response.dataId = std::nullopt ;
74+ response.description =
75+ " unable to get byte size for expression: " + args.name ;
17376 }
17477 }
17578 } else {
176- body. try_emplace ( " dataId" , nullptr ) ;
177- body. try_emplace ( " description" , " variable not found: " + name. str ()) ;
79+ response. dataId = std:: nullopt ;
80+ response. description = " variable not found: " + args. name ;
17881 }
17982
180- if (!body.getObject (" dataId" )) {
181- body.try_emplace (" dataId" , addr + " /" + size);
182- body.try_emplace (" accessTypes" , std::move (accessTypes));
183- body.try_emplace (" description" ,
184- size + " bytes at " + addr + " " + name.str ());
83+ if (!response.dataId .has_value ()) {
84+ response.dataId = addr + " /" + size;
85+ response.accessTypes = {protocol::eDataBreakpointAccessTypeRead,
86+ protocol::eDataBreakpointAccessTypeWrite,
87+ protocol::eDataBreakpointAccessTypeReadWrite};
88+ response.description = size + " bytes at " + addr + " " + args.name ;
18589 }
186- response. try_emplace ( " body " , std::move (body));
187- dap. SendJSON ( llvm::json::Value ( std::move ( response))) ;
90+
91+ return response;
18892}
18993
19094} // namespace lldb_dap
0 commit comments