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/// Decodes a memory reference from the given json value.
142///
143/// \param[in] v
144/// A JSON value that we expected to contain the memory reference.
145///
146/// \param[in] key
147/// The key of the memory reference.
148///
149/// \param[out] out
150/// The memory address, if successfully decoded.
151///
152/// \param[in] path
153/// The path for reporting errors.
154///
155/// \param[in] required
156/// Indicates if the key is required to be present, otherwise report an error
157/// if the key is missing.
158///
159/// \return
160/// Returns \b true if the address was decoded successfully.
161bool DecodeMemoryReference(const llvm::json::Value &v, llvm::StringLiteral key,
162 lldb::addr_t &out, llvm::json::Path path,
163 bool required);
164
165/// Extract an array of strings for the specified key from an object.
166///
167/// String values in the array will be extracted without any quotes
168/// around them. Numbers and Booleans will be converted into
169/// strings. Any NULL, array or objects values in the array will be
170/// ignored.
171///
172/// \param[in] obj
173/// A JSON object that we will attempt to extract the array from
174///
175/// \param[in] key
176/// The key to use when extracting the value
177///
178/// \return
179/// An array of string values for the specified \a key, or
180/// \a fail_value if there is no key that matches or if the
181/// value is not an array or all items in the array are not
182/// strings, numbers or booleans.
183std::vector<std::string> GetStrings(const llvm::json::Object *obj,
184 llvm::StringRef key);
185
186/// Extract an object of key value strings for the specified key from an object.
187///
188/// String values in the object will be extracted without any quotes
189/// around them. Numbers and Booleans will be converted into
190/// strings. Any NULL, array or objects values in the array will be
191/// ignored.
192///
193/// \param[in] obj
194/// A JSON object that we will attempt to extract the array from
195///
196/// \param[in] key
197/// The key to use when extracting the value
198///
199/// \return
200/// An object of key value strings for the specified \a key, or
201/// \a fail_value if there is no key that matches or if the
202/// value is not an object or key and values in the object are not
203/// strings, numbers or booleans.
204std::unordered_map<std::string, std::string>
205GetStringMap(const llvm::json::Object &obj, llvm::StringRef key);
206
207/// Fill a response object given the request object.
208///
209/// The \a response object will get its "type" set to "response",
210/// the "seq" set to zero, "response_seq" set to the "seq" value from
211/// \a request, "command" set to the "command" from \a request,
212/// and "success" set to true.
213///
214/// \param[in] request
215/// The request object received from a call to DAP::ReadJSON().
216///
217/// \param[in,out] response
218/// An empty llvm::json::Object object that will be filled
219/// in as noted in description.
220void FillResponse(const llvm::json::Object &request,
221 llvm::json::Object &response);
222
223/// Create a "Event" JSON object using \a event_name as the event name
224///
225/// \param[in] event_name
226/// The string value to use for the "event" key in the JSON object.
227///
228/// \return
229/// A "Event" JSON object with that follows the formal JSON
230/// definition outlined by Microsoft.
231llvm::json::Object CreateEventObject(const llvm::StringRef event_name);
232
233/// Create a "StackFrame" object for a LLDB frame object.
234///
235/// This function will fill in the following keys in the returned
236/// object:
237/// "id" - the stack frame ID as an integer
238/// "name" - the function name as a string
239/// "source" - source file information as a "Source" DAP object
240/// "line" - the source file line number as an integer
241/// "column" - the source file column number as an integer
242///
243/// \param[in] dap
244/// The DAP session associated with the stopped thread.
245///
246/// \param[in] frame
247/// The LLDB stack frame to use when populating out the "StackFrame"
248/// object.
249///
250/// \param[in] format
251/// The LLDB format to use when populating out the "StackFrame"
252/// object.
253///
254/// \return
255/// A "StackFrame" JSON object with that follows the formal JSON
256/// definition outlined by Microsoft.
257llvm::json::Value CreateStackFrame(DAP &dap, lldb::SBFrame &frame,
258 lldb::SBFormat &format);
259
260/// Create a "StackFrame" label object for a LLDB thread.
261///
262/// This function will fill in the following keys in the returned
263/// object:
264/// "id" - the thread ID as an integer
265/// "name" - the thread name as a string which combines the LLDB
266/// thread index ID along with the string name of the thread
267/// from the OS if it has a name.
268/// "presentationHint" - "label"
269///
270/// \param[in] thread
271/// The LLDB thread to use when populating out the "Thread"
272/// object.
273///
274/// \param[in] format
275/// The configured formatter for the DAP session.
276///
277/// \return
278/// A "StackFrame" JSON object with that follows the formal JSON
279/// definition outlined by Microsoft.
280llvm::json::Value CreateExtendedStackFrameLabel(lldb::SBThread &thread,
281 lldb::SBFormat &format);
282
283/// Create a "StoppedEvent" object for a LLDB thread object.
284///
285/// This function will fill in the following keys in the returned
286/// object's "body" object:
287/// "reason" - With a valid stop reason enumeration string value
288/// that Microsoft specifies
289/// "threadId" - The thread ID as an integer
290/// "description" - a stop description (like "breakpoint 12.3") as a
291/// string
292/// "preserveFocusHint" - a boolean value that states if this thread
293/// should keep the focus in the GUI.
294/// "allThreadsStopped" - set to True to indicate that all threads
295/// stop when any thread stops.
296///
297/// \param[in] dap
298/// The DAP session associated with the stopped thread.
299///
300/// \param[in] thread
301/// The LLDB thread to use when populating out the "StoppedEvent"
302/// object.
303///
304/// \param[in] stop_id
305/// The stop id for this event.
306///
307/// \return
308/// A "StoppedEvent" JSON object with that follows the formal JSON
309/// definition outlined by Microsoft.
310llvm::json::Value CreateThreadStopped(DAP &dap, lldb::SBThread &thread,
311 uint32_t stop_id);
312
313/// \return
314/// The variable name of \a value or a default placeholder.
315const char *GetNonNullVariableName(lldb::SBValue &value);
316
317/// VSCode can't display two variables with the same name, so we need to
318/// distinguish them by using a suffix.
319///
320/// If the source and line information is present, we use it as the suffix.
321/// Otherwise, we fallback to the variable address or register location.
322std::string CreateUniqueVariableNameForDisplay(lldb::SBValue &v,
323 bool is_name_duplicated);
324
325/// Helper struct that parses the metadata of an \a lldb::SBValue and produces
326/// a canonical set of properties that can be sent to DAP clients.
327struct VariableDescription {
328 // The error message if SBValue.GetValue() fails.
329 std::optional<std::string> error;
330 // The display description to show on the IDE.
331 std::string display_value;
332 // The display name to show on the IDE.
333 std::string name;
334 // The variable path for this variable.
335 std::string evaluate_name;
336 // The output of SBValue.GetValue() if it doesn't fail. It might be empty.
337 std::string value;
338 // The summary string of this variable. It might be empty.
339 std::string summary;
340 // The auto summary if using `enableAutoVariableSummaries`.
341 std::optional<std::string> auto_summary;
342 // The type of this variable.
343 lldb::SBType type_obj;
344 // The display type name of this variable.
345 std::string display_type_name;
346 /// The SBValue for this variable.
347 lldb::SBValue v;
348
349 VariableDescription(lldb::SBValue v, bool auto_variable_summaries,
350 bool format_hex = false, bool is_name_duplicated = false,
351 std::optional<std::string> custom_name = {});
352
353 /// Returns a description of the value appropriate for the specified context.
354 std::string GetResult(llvm::StringRef context);
355};
356
357/// Does the given variable have an associated value location?
358bool ValuePointsToCode(lldb::SBValue v);
359
360/// Pack a location into a single integer which we can send via
361/// the debug adapter protocol.
362int64_t PackLocation(int64_t var_ref, bool is_value_location);
363
364/// Reverse of `PackLocation`
365std::pair<int64_t, bool> UnpackLocation(int64_t location_id);
366
367llvm::json::Value CreateCompileUnit(lldb::SBCompileUnit &unit);
368
369/// Create a runInTerminal reverse request object
370///
371/// \param[in] program
372/// Path to the program to run in the terminal.
373///
374/// \param[in] args
375/// The arguments for the program.
376///
377/// \param[in] env
378/// The environment variables to set in the terminal.
379///
380/// \param[in] cwd
381/// The working directory for the run in terminal request.
382///
383/// \param[in] comm_file
384/// The fifo file used to communicate the with the target launcher.
385///
386/// \param[in] debugger_pid
387/// The PID of the lldb-dap instance that will attach to the target. The
388/// launcher uses it on Linux tell the kernel that it should allow the
389/// debugger process to attach.
390///
391/// \param[in] external
392/// If set to true, the program will run in an external terminal window
393/// instead of IDE's integrated terminal.
394///
395/// \return
396/// A "runInTerminal" JSON object that follows the specification outlined by
397/// Microsoft.
398llvm::json::Object CreateRunInTerminalReverseRequest(
399 llvm::StringRef program, const std::vector<std::string> &args,
400 const llvm::StringMap<std::string> &env, llvm::StringRef cwd,
401 llvm::StringRef comm_file, lldb::pid_t debugger_pid, bool external);
402
403/// Create a "Terminated" JSON object that contains statistics
404///
405/// \return
406/// A body JSON object with debug info and breakpoint info
407llvm::json::Object CreateTerminatedEventObject(lldb::SBTarget &target);
408
409/// Convert a given JSON object to a string.
410std::string JSONToString(const llvm::json::Value &json);
411
412} // namespace lldb_dap
413
414#endif
415

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