LLDB mainline
Resource.cpp
Go to the documentation of this file.
1// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2// See https://llvm.org/LICENSE.txt for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4//
5//===----------------------------------------------------------------------===//
6
7#include "Resource.h"
9#include "lldb/Core/Module.h"
11
12using namespace lldb_private;
13using namespace lldb_private::mcp;
14using namespace lldb_protocol::mcp;
15
16namespace {
17struct DebuggerResource {
18 uint64_t debugger_id = 0;
19 std::string name;
20 uint64_t num_targets = 0;
21};
22
23llvm::json::Value toJSON(const DebuggerResource &DR) {
24 llvm::json::Object Result{{"debugger_id", DR.debugger_id},
25 {"num_targets", DR.num_targets}};
26 if (!DR.name.empty())
27 Result.insert({"name", DR.name});
28 return Result;
29}
30
31struct TargetResource {
32 size_t debugger_id = 0;
33 size_t target_idx = 0;
34 bool selected = false;
35 bool dummy = false;
36 std::string arch;
37 std::string path;
38 std::string platform;
39};
40
41llvm::json::Value toJSON(const TargetResource &TR) {
42 llvm::json::Object Result{{"debugger_id", TR.debugger_id},
43 {"target_idx", TR.target_idx},
44 {"selected", TR.selected},
45 {"dummy", TR.dummy}};
46 if (!TR.arch.empty())
47 Result.insert({"arch", TR.arch});
48 if (!TR.path.empty())
49 Result.insert({"path", TR.path});
50 if (!TR.platform.empty())
51 Result.insert({"platform", TR.platform});
52 return Result;
53}
54} // namespace
55
56static constexpr llvm::StringLiteral kMimeTypeJSON = "application/json";
57
58template <typename... Args>
59static llvm::Error createStringError(const char *format, Args &&...args) {
60 return llvm::createStringError(
61 llvm::formatv(format, std::forward<Args>(args)...).str());
62}
63
64static llvm::Error createUnsupportedURIError(llvm::StringRef uri) {
65 return llvm::make_error<UnsupportedURI>(uri.str());
66}
67
70 const lldb::user_id_t debugger_id = debugger.GetID();
71
73 resource.uri = llvm::formatv("lldb://debugger/{0}", debugger_id);
74 resource.name = debugger.GetInstanceName();
75 resource.description =
76 llvm::formatv("Information about debugger instance {0}: {1}", debugger_id,
77 debugger.GetInstanceName());
78 resource.mimeType = kMimeTypeJSON;
79 return resource;
80}
81
84 const size_t debugger_id = target.GetDebugger().GetID();
85
86 std::string target_name = llvm::formatv("target {0}", target_idx);
87
88 if (Module *exe_module = target.GetExecutableModulePointer())
89 target_name = exe_module->GetFileSpec().GetFilename().GetString();
90
92 resource.uri =
93 llvm::formatv("lldb://debugger/{0}/target/{1}", debugger_id, target_idx);
94 resource.name = target_name;
95 resource.description =
96 llvm::formatv("Information about target {0} in debugger instance {1}",
97 target_idx, debugger_id);
98 resource.mimeType = kMimeTypeJSON;
99 return resource;
100}
101
102std::vector<lldb_protocol::mcp::Resource>
104 std::vector<lldb_protocol::mcp::Resource> resources;
105
106 const size_t num_debuggers = Debugger::GetNumDebuggers();
107 for (size_t i = 0; i < num_debuggers; ++i) {
109 if (!debugger_sp)
110 continue;
111 resources.emplace_back(GetDebuggerResource(*debugger_sp));
112
113 TargetList &target_list = debugger_sp->GetTargetList();
114 const size_t num_targets = target_list.GetNumTargets();
115 for (size_t j = 0; j < num_targets; ++j) {
116 lldb::TargetSP target_sp = target_list.GetTargetAtIndex(j);
117 if (!target_sp)
118 continue;
119 resources.emplace_back(GetTargetResource(j, *target_sp));
120 }
121 }
122
123 return resources;
124}
125
126llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
127DebuggerResourceProvider::ReadResource(llvm::StringRef uri) const {
128
129 auto [protocol, path] = uri.split("://");
130
131 if (protocol != "lldb")
132 return createUnsupportedURIError(uri);
133
134 llvm::SmallVector<llvm::StringRef, 4> components;
135 path.split(components, '/');
136
137 if (components.size() < 2)
138 return createUnsupportedURIError(uri);
139
140 if (components[0] != "debugger")
141 return createUnsupportedURIError(uri);
142
143 size_t debugger_idx;
144 if (components[1].getAsInteger(0, debugger_idx))
145 return createStringError("invalid debugger id '{0}': {1}", components[1],
146 path);
147
148 if (components.size() > 3) {
149 if (components[2] != "target")
150 return createUnsupportedURIError(uri);
151
152 size_t target_idx;
153 if (components[3].getAsInteger(0, target_idx))
154 return createStringError("invalid target id '{0}': {1}", components[3],
155 path);
156
157 return ReadTargetResource(uri, debugger_idx, target_idx);
158 }
159
160 return ReadDebuggerResource(uri, debugger_idx);
161}
162
163llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
165 lldb::user_id_t debugger_id) {
166 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);
167 if (!debugger_sp)
168 return createStringError("invalid debugger id: {0}", debugger_id);
169
170 DebuggerResource debugger_resource;
171 debugger_resource.debugger_id = debugger_id;
172 debugger_resource.name = debugger_sp->GetInstanceName();
173 debugger_resource.num_targets = debugger_sp->GetTargetList().GetNumTargets();
174
176 contents.uri = uri;
177 contents.mimeType = kMimeTypeJSON;
178 contents.text = llvm::formatv("{0}", toJSON(debugger_resource));
179
181 result.contents.push_back(contents);
182 return result;
183}
184
185llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
187 lldb::user_id_t debugger_id,
188 size_t target_idx) {
189
190 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);
191 if (!debugger_sp)
192 return createStringError("invalid debugger id: {0}", debugger_id);
193
194 TargetList &target_list = debugger_sp->GetTargetList();
195 lldb::TargetSP target_sp = target_list.GetTargetAtIndex(target_idx);
196 if (!target_sp)
197 return createStringError("invalid target idx: {0}", target_idx);
198
199 TargetResource target_resource;
200 target_resource.debugger_id = debugger_id;
201 target_resource.target_idx = target_idx;
202 target_resource.arch = target_sp->GetArchitecture().GetTriple().str();
203 target_resource.dummy = target_sp->IsDummyTarget();
204 target_resource.selected = target_sp == debugger_sp->GetSelectedTarget();
205
206 if (Module *exe_module = target_sp->GetExecutableModulePointer())
207 target_resource.path = exe_module->GetFileSpec().GetPath();
208 if (lldb::PlatformSP platform_sp = target_sp->GetPlatform())
209 target_resource.platform = platform_sp->GetName();
210
212 contents.uri = uri;
213 contents.mimeType = kMimeTypeJSON;
214 contents.text = llvm::formatv("{0}", toJSON(target_resource));
215
217 result.contents.push_back(contents);
218 return result;
219}
static constexpr llvm::StringLiteral kMimeTypeJSON
Definition: Resource.cpp:56
static llvm::Error createUnsupportedURIError(llvm::StringRef uri)
Definition: Resource.cpp:64
static llvm::Error createStringError(const char *format, Args &&...args)
Definition: Resource.cpp:59
A command line argument class.
Definition: Args.h:33
A class to manage flag bits.
Definition: Debugger.h:80
static lldb::DebuggerSP GetDebuggerAtIndex(size_t index)
Definition: Debugger.cpp:1523
const std::string & GetInstanceName() const
Definition: Debugger.h:370
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id)
Definition: Debugger.cpp:1535
static size_t GetNumDebuggers()
Definition: Debugger.cpp:1515
A class that describes an executable image and its associated object and symbol files.
Definition: Module.h:90
lldb::TargetSP GetTargetAtIndex(uint32_t index) const
Definition: TargetList.cpp:499
size_t GetNumTargets() const
Definition: TargetList.cpp:494
Module * GetExecutableModulePointer()
Definition: Target.cpp:1533
Debugger & GetDebugger() const
Definition: Target.h:1097
llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadResource(llvm::StringRef uri) const override
Definition: Resource.cpp:127
static llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadTargetResource(llvm::StringRef uri, lldb::user_id_t debugger_id, size_t target_idx)
Definition: Resource.cpp:186
static lldb_protocol::mcp::Resource GetDebuggerResource(Debugger &debugger)
Definition: Resource.cpp:69
static lldb_protocol::mcp::Resource GetTargetResource(size_t target_idx, Target &target)
Definition: Resource.cpp:83
static llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadDebuggerResource(llvm::StringRef uri, lldb::user_id_t debugger_id)
Definition: Resource.cpp:164
std::vector< lldb_protocol::mcp::Resource > GetResources() const override
Definition: Resource.cpp:103
A class that represents a running process on the host machine.
llvm::json::Value toJSON(const TraceSupportedResponse &packet)
llvm::json::Value toJSON(const Request &)
Definition: Protocol.cpp:66
std::shared_ptr< lldb_private::Platform > PlatformSP
Definition: lldb-forward.h:391
std::shared_ptr< lldb_private::Debugger > DebuggerSP
Definition: lldb-forward.h:342
uint64_t user_id_t
Definition: lldb-types.h:82
std::shared_ptr< lldb_private::Target > TargetSP
Definition: lldb-forward.h:456
lldb::user_id_t GetID() const
Get accessor for the user ID.
Definition: UserID.h:47
The server's response to a resources/read request from the client.
Definition: Protocol.h:161
std::vector< TextResourceContents > contents
Definition: Protocol.h:162
A known resource that the server is capable of reading.
Definition: Protocol.h:108
std::string description
A description of what this resource represents.
Definition: Protocol.h:116
std::string uri
The URI of this resource.
Definition: Protocol.h:110
std::string mimeType
The MIME type of this resource, if known.
Definition: Protocol.h:119
std::string name
A human-readable name for this resource.
Definition: Protocol.h:113
The contents of a specific resource or sub-resource.
Definition: Protocol.h:134
std::string text
The text of the item.
Definition: Protocol.h:140
std::string uri
The URI of this resource.
Definition: Protocol.h:136
std::string mimeType
The MIME type of this resource, if known.
Definition: Protocol.h:143