1//===-- JSONUtils.h ---------------------------------------------*- C++ -*-===//
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#ifndef LLDB_TOOLS_LLDB_DAP_JSONUTILS_H
10#define LLDB_TOOLS_LLDB_DAP_JSONUTILS_H
11
12#include "DAPForward.h"
13#include "Protocol/ProtocolTypes.h"
14#include "lldb/API/SBCompileUnit.h"
15#include "lldb/API/SBFormat.h"
16#include "lldb/API/SBType.h"
17#include "lldb/API/SBValue.h"
18#include "lldb/lldb-types.h"
19#include "llvm/ADT/StringMap.h"
20#include "llvm/ADT/StringRef.h"
21#include "llvm/Support/JSON.h"
22#include <cstdint>
23#include <optional>
24#include <string>
25#include <unordered_map>
26#include <utility>
27#include <vector>
28
29namespace lldb_dap {
30
31/// Emplace a StringRef in a json::Object after enusring that the
32/// string is valid UTF8. If not, first call llvm::json::fixUTF8
33/// before emplacing.
34///
35/// \param[in] obj
36/// A JSON object that we will attempt to emplace the value in
37///
38/// \param[in] key
39/// The key to use when emplacing the value
40///
41/// \param[in] str
42/// The string to emplace
43void EmplaceSafeString(llvm::json::Object &obj, llvm::StringRef key,
44 llvm::StringRef str);
45
46/// Extract simple values as a string.
47///
48/// \param[in] value
49/// A JSON value to extract the string from.
50///
51/// \return
52/// A llvm::StringRef that contains the string value, or an empty
53/// string if \a value isn't a string.
54llvm::StringRef GetAsString(const llvm::json::Value &value);
55
56/// Extract the string value for the specified key from the
57/// specified object.
58///
59/// \param[in] obj
60/// A JSON object that we will attempt to extract the value from
61///
62/// \param[in] key
63/// The key to use when extracting the value
64///
65/// \return
66/// A llvm::StringRef that contains the string value for the
67/// specified \a key, or \a std::nullopt if there is no key that
68/// matches or if the value is not a string.
69std::optional<llvm::StringRef> GetString(const llvm::json::Object &obj,
70 llvm::StringRef key);
71std::optional<llvm::StringRef> GetString(const llvm::json::Object *obj,
72 llvm::StringRef key);
73
74/// Extract the integer value for the specified key from the specified object
75/// and return it as the specified integer type T.
76///
77/// \param[in] obj
78/// A JSON object that we will attempt to extract the value from
79///
80/// \param[in] key
81/// The key to use when extracting the value
82///
83/// \return
84/// The integer value for the specified \a key, or std::nullopt if there is
85/// no key that matches or if the value is not an integer.
86/// @{
87template <typename T>
88std::optional<T> GetInteger(const llvm::json::Object &obj,
89 llvm::StringRef key) {
90 return obj.getInteger(K: key);
91}
92
93template <typename T>
94std::optional<T> GetInteger(const llvm::json::Object *obj,
95 llvm::StringRef key) {
96 if (obj != nullptr)
97 return GetInteger<T>(*obj, key);
98 return std::nullopt;
99}
100/// @}
101
102/// Extract the boolean value for the specified key from the
103/// specified object.
104///
105/// \param[in] obj
106/// A JSON object that we will attempt to extract the value from
107///
108/// \param[in] key
109/// The key to use when extracting the value
110///
111/// \return
112/// The boolean value for the specified \a key, or std::nullopt
113/// if there is no key that matches or if the value is not a
114/// boolean value of an integer.
115/// @{
116std::optional<bool> GetBoolean(const llvm::json::Object &obj,
117 llvm::StringRef key);
118std::optional<bool> GetBoolean(const llvm::json::Object *obj,
119 llvm::StringRef key);
120/// @}
121
122/// Check if the specified key exists in the specified object.
123///
124/// \param[in] obj
125/// A JSON object that we will attempt to extract the value from
126///
127/// \param[in] key
128/// The key to check for
129///
130/// \return
131/// \b True if the key exists in the \a obj, \b False otherwise.
132bool ObjectContainsKey(const llvm::json::Object &obj, llvm::StringRef key);
133
134/// Encodes a memory reference
135std::string EncodeMemoryReference(lldb::addr_t addr);
136
137/// Decodes a memory reference
138std::optional<lldb::addr_t>
139DecodeMemoryReference(llvm::StringRef memoryReference);
140
141/// Extract an array of strings for the specified key from an object.
142///
143/// String values in the array will be extracted without any quotes
144/// around them. Numbers and Booleans will be converted into
145/// strings. Any NULL, array or objects values in the array will be
146/// ignored.
147///
148/// \param[in] obj
149/// A JSON object that we will attempt to extract the array from
150///
151/// \param[in] key
152/// The key to use when extracting the value
153///
154/// \return
155/// An array of string values for the specified \a key, or
156/// \a fail_value if there is no key that matches or if the
157/// value is not an array or all items in the array are not
158/// strings, numbers or booleans.
159std::vector<std::string> GetStrings(const llvm::json::Object *obj,
160 llvm::StringRef key);
161
162/// Extract an object of key value strings for the specified key from an object.
163///
164/// String values in the object will be extracted without any quotes
165/// around them. Numbers and Booleans will be converted into
166/// strings. Any NULL, array or objects values in the array will be
167/// ignored.
168///
169/// \param[in] obj
170/// A JSON object that we will attempt to extract the array from
171///
172/// \param[in] key
173/// The key to use when extracting the value
174///
175/// \return
176/// An object of key value strings for the specified \a key, or
177/// \a fail_value if there is no key that matches or if the
178/// value is not an object or key and values in the object are not
179/// strings, numbers or booleans.
180std::unordered_map<std::string, std::string>
181GetStringMap(const llvm::json::Object &obj, llvm::StringRef key);
182
183/// Fill a response object given the request object.
184///
185/// The \a response object will get its "type" set to "response",
186/// the "seq" set to zero, "response_seq" set to the "seq" value from
187/// \a request, "command" set to the "command" from \a request,
188/// and "success" set to true.
189///
190/// \param[in] request
191/// The request object received from a call to DAP::ReadJSON().
192///
193/// \param[in,out] response
194/// An empty llvm::json::Object object that will be filled
195/// in as noted in description.
196void FillResponse(const llvm::json::Object &request,
197 llvm::json::Object &response);
198
199/// Converts a LLDB module to a VS Code DAP module for use in "modules" events.
200///
201/// \param[in] target
202/// A LLDB target object to convert into a JSON value.
203///
204/// \param[in] module
205/// A LLDB module object to convert into a JSON value
206///
207/// \param[in] id_only
208/// Only include the module ID in the JSON value. This is used when sending
209/// a "removed" module event.
210///
211/// \return
212/// A "Module" JSON object with that follows the formal JSON
213/// definition outlined by Microsoft.
214llvm::json::Value CreateModule(lldb::SBTarget &target, lldb::SBModule &module,
215 bool id_only = false);
216
217/// Create a "Event" JSON object using \a event_name as the event name
218///
219/// \param[in] event_name
220/// The string value to use for the "event" key in the JSON object.
221///
222/// \return
223/// A "Event" JSON object with that follows the formal JSON
224/// definition outlined by Microsoft.
225llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
226
227/// Create a "ExceptionBreakpointsFilter" JSON object as described in
228/// the debug adapter definition.
229///
230/// \param[in] bp
231/// The exception breakpoint object to use
232///
233/// \return
234/// A "ExceptionBreakpointsFilter" JSON object with that follows
235/// the formal JSON definition outlined by Microsoft.
236protocol::ExceptionBreakpointsFilter
237CreateExceptionBreakpointFilter(const ExceptionBreakpoint &bp);
238
239/// Create a "StackFrame" object for a LLDB frame object.
240///
241/// This function will fill in the following keys in the returned
242/// object:
243/// "id" - the stack frame ID as an integer
244/// "name" - the function name as a string
245/// "source" - source file information as a "Source" DAP object
246/// "line" - the source file line number as an integer
247/// "column" - the source file column number as an integer
248///
249/// \param[in] frame
250/// The LLDB stack frame to use when populating out the "StackFrame"
251/// object.
252///
253/// \param[in] format
254/// The LLDB format to use when populating out the "StackFrame"
255/// object.
256///
257/// \return
258/// A "StackFrame" JSON object with that follows the formal JSON
259/// definition outlined by Microsoft.
260llvm::json::Value CreateStackFrame(lldb::SBFrame &frame,
261 lldb::SBFormat &format);
262
263/// Create a "StackFrame" label object for a LLDB thread.
264///
265/// This function will fill in the following keys in the returned
266/// object:
267/// "id" - the thread ID as an integer
268/// "name" - the thread name as a string which combines the LLDB
269/// thread index ID along with the string name of the thread
270/// from the OS if it has a name.
271/// "presentationHint" - "label"
272///
273/// \param[in] thread
274/// The LLDB thread to use when populating out the "Thread"
275/// object.
276///
277/// \param[in] format
278/// The configured formatter for the DAP session.
279///
280/// \return
281/// A "StackFrame" JSON object with that follows the formal JSON
282/// definition outlined by Microsoft.
283llvm::json::Value CreateExtendedStackFrameLabel(lldb::SBThread &thread,
284 lldb::SBFormat &format);
285
286/// Create a "StoppedEvent" object for a LLDB thread object.
287///
288/// This function will fill in the following keys in the returned
289/// object's "body" object:
290/// "reason" - With a valid stop reason enumeration string value
291/// that Microsoft specifies
292/// "threadId" - The thread ID as an integer
293/// "description" - a stop description (like "breakpoint 12.3") as a
294/// string
295/// "preserveFocusHint" - a boolean value that states if this thread
296/// should keep the focus in the GUI.
297/// "allThreadsStopped" - set to True to indicate that all threads
298/// stop when any thread stops.
299///
300/// \param[in] dap
301/// The DAP session associated with the stopped thread.
302///
303/// \param[in] thread
304/// The LLDB thread to use when populating out the "StoppedEvent"
305/// object.
306///
307/// \param[in] stop_id
308/// The stop id for this event.
309///
310/// \return
311/// A "StoppedEvent" JSON object with that follows the formal JSON
312/// definition outlined by Microsoft.
313llvm::json::Value CreateThreadStopped(DAP &dap, lldb::SBThread &thread,
314 uint32_t stop_id);
315
316/// \return
317/// The variable name of \a value or a default placeholder.
318const char *GetNonNullVariableName(lldb::SBValue &value);
319
320/// VSCode can't display two variables with the same name, so we need to
321/// distinguish them by using a suffix.
322///
323/// If the source and line information is present, we use it as the suffix.
324/// Otherwise, we fallback to the variable address or register location.
325std::string CreateUniqueVariableNameForDisplay(lldb::SBValue &v,
326 bool is_name_duplicated);
327
328/// Helper struct that parses the metadata of an \a lldb::SBValue and produces
329/// a canonical set of properties that can be sent to DAP clients.
330struct VariableDescription {
331 // The error message if SBValue.GetValue() fails.
332 std::optional<std::string> error;
333 // The display description to show on the IDE.
334 std::string display_value;
335 // The display name to show on the IDE.
336 std::string name;
337 // The variable path for this variable.
338 std::string evaluate_name;
339 // The output of SBValue.GetValue() if it doesn't fail. It might be empty.
340 std::string value;
341 // The summary string of this variable. It might be empty.
342 std::string summary;
343 // The auto summary if using `enableAutoVariableSummaries`.
344 std::optional<std::string> auto_summary;
345 // The type of this variable.
346 lldb::SBType type_obj;
347 // The display type name of this variable.
348 std::string display_type_name;
349 /// The SBValue for this variable.
350 lldb::SBValue v;
351
352 VariableDescription(lldb::SBValue v, bool auto_variable_summaries,
353 bool format_hex = false, bool is_name_duplicated = false,
354 std::optional<std::string> custom_name = {});
355
356 /// Create a JSON object that represents these extensions to the DAP variable
357 /// response.
358 llvm::json::Object GetVariableExtensionsJSON();
359
360 /// Returns a description of the value appropriate for the specified context.
361 std::string GetResult(llvm::StringRef context);
362};
363
364/// Does the given variable have an associated value location?
365bool ValuePointsToCode(lldb::SBValue v);
366
367/// Pack a location into a single integer which we can send via
368/// the debug adapter protocol.
369int64_t PackLocation(int64_t var_ref, bool is_value_location);
370
371/// Reverse of `PackLocation`
372std::pair<int64_t, bool> UnpackLocation(int64_t location_id);
373
374/// Create a "Variable" object for a LLDB thread object.
375///
376/// This function will fill in the following keys in the returned
377/// object:
378/// "name" - the name of the variable
379/// "value" - the value of the variable as a string
380/// "type" - the typename of the variable as a string
381/// "id" - a unique identifier for a value in case there are multiple
382/// variables with the same name. Other parts of the DAP
383/// protocol refer to values by name so this can help
384/// disambiguate such cases if a IDE passes this "id" value
385/// back down.
386/// "variablesReference" - Zero if the variable has no children,
387/// non-zero integer otherwise which can be used to expand
388/// the variable.
389/// "evaluateName" - The name of the variable to use in expressions
390/// as a string.
391///
392/// \param[in] v
393/// The LLDB value to use when populating out the "Variable"
394/// object.
395///
396/// \param[in] var_ref
397/// The variable reference. Used to identify the value, e.g.
398/// in the `variablesReference` or `declarationLocationReference`
399/// properties.
400///
401/// \param[in] format_hex
402/// If set to true the variable will be formatted as hex in
403/// the "value" key value pair for the value of the variable.
404///
405/// \param[in] auto_variable_summaries
406/// IF set to true the variable will create an automatic variable summary.
407///
408/// \param[in] is_name_duplicated
409/// Whether the same variable name appears multiple times within the same
410/// context (e.g. locals). This can happen due to shadowed variables in
411/// nested blocks.
412///
413/// As VSCode doesn't render two of more variables with the same name, we
414/// apply a suffix to distinguish duplicated variables.
415///
416/// \param[in] custom_name
417/// A provided custom name that is used instead of the SBValue's when
418/// creating the JSON representation.
419///
420/// \return
421/// A "Variable" JSON object with that follows the formal JSON
422/// definition outlined by Microsoft.
423llvm::json::Value CreateVariable(lldb::SBValue v, int64_t var_ref,
424 bool format_hex, bool auto_variable_summaries,
425 bool synthetic_child_debugging,
426 bool is_name_duplicated = false,
427 std::optional<std::string> custom_name = {});
428
429llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit);
430
431/// Create a runInTerminal reverse request object
432///
433/// \param[in] program
434/// Path to the program to run in the terminal.
435///
436/// \param[in] args
437/// The arguments for the program.
438///
439/// \param[in] env
440/// The environment variables to set in the terminal.
441///
442/// \param[in] cwd
443/// The working directory for the run in terminal request.
444///
445/// \param[in] comm_file
446/// The fifo file used to communicate the with the target launcher.
447///
448/// \param[in] debugger_pid
449/// The PID of the lldb-dap instance that will attach to the target. The
450/// launcher uses it on Linux tell the kernel that it should allow the
451/// debugger process to attach.
452///
453/// \return
454/// A "runInTerminal" JSON object that follows the specification outlined by
455/// Microsoft.
456llvm::json::Object CreateRunInTerminalReverseRequest(
457 llvm::StringRef program, const std::vector<std::string> &args,
458 const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
459 llvm::StringRef comm_file, lldb::pid_t debugger_pid);
460
461/// Create a "Terminated" JSON object that contains statistics
462///
463/// \return
464/// A body JSON object with debug info and breakpoint info
465llvm::json::Object CreateTerminatedEventObject(lldb::SBTarget &target);
466
467/// Convert a given JSON object to a string.
468std::string JSONToString(const llvm::json::Value &json);
469
470} // namespace lldb_dap
471
472#endif
473

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of lldb/tools/lldb-dap/JSONUtils.h