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#include "llvm/Support/ErrorExtras.h"
12
13using namespace lldb_private;
14using namespace lldb_private::mcp;
15using namespace lldb_protocol::mcp;
16
17namespace {
18struct DebuggerResource {
19 uint64_t debugger_id = 0;
20 std::string name;
21 uint64_t num_targets = 0;
22};
23
24llvm::json::Value toJSON(const DebuggerResource &DR) {
25 llvm::json::Object Result{{"debugger_id", DR.debugger_id},
26 {"num_targets", DR.num_targets}};
27 if (!DR.name.empty())
28 Result.insert({"name", DR.name});
29 return Result;
30}
31
32struct TargetResource {
33 size_t debugger_id = 0;
34 size_t target_idx = 0;
35 bool selected = false;
36 bool dummy = false;
37 std::string arch;
38 std::string path;
39 std::string platform;
40};
41
42llvm::json::Value toJSON(const TargetResource &TR) {
43 llvm::json::Object Result{{"debugger_id", TR.debugger_id},
44 {"target_idx", TR.target_idx},
45 {"selected", TR.selected},
46 {"dummy", TR.dummy}};
47 if (!TR.arch.empty())
48 Result.insert({"arch", TR.arch});
49 if (!TR.path.empty())
50 Result.insert({"path", TR.path});
51 if (!TR.platform.empty())
52 Result.insert({"platform", TR.platform});
53 return Result;
54}
55} // namespace
56
57static constexpr llvm::StringLiteral kMimeTypeJSON = "application/json";
58
59static llvm::Error createUnsupportedURIError(llvm::StringRef uri) {
60 return llvm::make_error<UnsupportedURI>(uri.str());
61}
62
65 const lldb::user_id_t debugger_id = debugger.GetID();
66
68 resource.uri = llvm::formatv("lldb://debugger/{0}", debugger_id);
69 resource.name = debugger.GetInstanceName();
70 resource.description =
71 llvm::formatv("Information about debugger instance {0}: {1}", debugger_id,
72 debugger.GetInstanceName());
73 resource.mimeType = kMimeTypeJSON;
74 return resource;
75}
76
79 const size_t debugger_id = target.GetDebugger().GetID();
80
81 std::string target_name = llvm::formatv("target {0}", target_idx);
82
83 if (Module *exe_module = target.GetExecutableModulePointer())
84 target_name = exe_module->GetFileSpec().GetFilename().GetString();
85
87 resource.uri =
88 llvm::formatv("lldb://debugger/{0}/target/{1}", debugger_id, target_idx);
89 resource.name = target_name;
90 resource.description =
91 llvm::formatv("Information about target {0} in debugger instance {1}",
92 target_idx, debugger_id);
93 resource.mimeType = kMimeTypeJSON;
94 return resource;
95}
96
97std::vector<lldb_protocol::mcp::Resource>
99 std::vector<lldb_protocol::mcp::Resource> resources;
100
101 const size_t num_debuggers = Debugger::GetNumDebuggers();
102 for (size_t i = 0; i < num_debuggers; ++i) {
104 if (!debugger_sp)
105 continue;
106 resources.emplace_back(GetDebuggerResource(*debugger_sp));
107
108 TargetList &target_list = debugger_sp->GetTargetList();
109 const size_t num_targets = target_list.GetNumTargets();
110 for (size_t j = 0; j < num_targets; ++j) {
111 lldb::TargetSP target_sp = target_list.GetTargetAtIndex(j);
112 if (!target_sp)
113 continue;
114 resources.emplace_back(GetTargetResource(j, *target_sp));
115 }
116 }
117
118 return resources;
119}
120
121llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
122DebuggerResourceProvider::ReadResource(llvm::StringRef uri) const {
123
124 auto [protocol, path] = uri.split("://");
125
126 if (protocol != "lldb")
127 return createUnsupportedURIError(uri);
128
129 llvm::SmallVector<llvm::StringRef, 4> components;
130 path.split(components, '/');
131
132 if (components.size() < 2)
133 return createUnsupportedURIError(uri);
134
135 if (components[0] != "debugger")
136 return createUnsupportedURIError(uri);
137
138 size_t debugger_idx;
139 if (components[1].getAsInteger(0, debugger_idx))
140 return llvm::createStringErrorV("invalid debugger id '{0}': {1}",
141 components[1], path);
142
143 if (components.size() > 3) {
144 if (components[2] != "target")
145 return createUnsupportedURIError(uri);
146
147 size_t target_idx;
148 if (components[3].getAsInteger(0, target_idx))
149 return llvm::createStringErrorV("invalid target id '{0}': {1}",
150 components[3], path);
151
152 return ReadTargetResource(uri, debugger_idx, target_idx);
153 }
154
155 return ReadDebuggerResource(uri, debugger_idx);
156}
157
158llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
160 lldb::user_id_t debugger_id) {
161 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);
162 if (!debugger_sp)
163 return llvm::createStringErrorV("invalid debugger id: {0}", debugger_id);
164
165 DebuggerResource debugger_resource;
166 debugger_resource.debugger_id = debugger_id;
167 debugger_resource.name = debugger_sp->GetInstanceName();
168 debugger_resource.num_targets = debugger_sp->GetTargetList().GetNumTargets();
169
171 contents.uri = uri;
172 contents.mimeType = kMimeTypeJSON;
173 contents.text = llvm::formatv("{0}", toJSON(debugger_resource));
174
176 result.contents.push_back(contents);
177 return result;
178}
179
180llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
182 lldb::user_id_t debugger_id,
183 size_t target_idx) {
184
185 lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);
186 if (!debugger_sp)
187 return llvm::createStringErrorV("invalid debugger id: {0}", debugger_id);
188
189 TargetList &target_list = debugger_sp->GetTargetList();
190 lldb::TargetSP target_sp = target_list.GetTargetAtIndex(target_idx);
191 if (!target_sp)
192 return llvm::createStringErrorV("invalid target idx: {0}", target_idx);
193
194 TargetResource target_resource;
195 target_resource.debugger_id = debugger_id;
196 target_resource.target_idx = target_idx;
197 target_resource.arch = target_sp->GetArchitecture().GetTriple().str();
198 target_resource.dummy = target_sp->IsDummyTarget();
199 target_resource.selected = target_sp == debugger_sp->GetSelectedTarget();
200
201 if (Module *exe_module = target_sp->GetExecutableModulePointer())
202 target_resource.path = exe_module->GetFileSpec().GetPath();
203 if (lldb::PlatformSP platform_sp = target_sp->GetPlatform())
204 target_resource.platform = platform_sp->GetName();
205
207 contents.uri = uri;
208 contents.mimeType = kMimeTypeJSON;
209 contents.text = llvm::formatv("{0}", toJSON(target_resource));
210
212 result.contents.push_back(contents);
213 return result;
214}
static constexpr llvm::StringLiteral kMimeTypeJSON
Definition Resource.cpp:57
static llvm::Error createUnsupportedURIError(llvm::StringRef uri)
Definition Resource.cpp:59
A class to manage flag bits.
Definition Debugger.h:87
static lldb::DebuggerSP GetDebuggerAtIndex(size_t index)
const std::string & GetInstanceName() const
Definition Debugger.h:386
static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id)
static size_t GetNumDebuggers()
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
size_t GetNumTargets() const
Module * GetExecutableModulePointer()
Definition Target.cpp:1541
Debugger & GetDebugger() const
Definition Target.h:1224
llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadResource(llvm::StringRef uri) const override
Definition Resource.cpp:122
static llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadTargetResource(llvm::StringRef uri, lldb::user_id_t debugger_id, size_t target_idx)
Definition Resource.cpp:181
static lldb_protocol::mcp::Resource GetDebuggerResource(Debugger &debugger)
Definition Resource.cpp:64
static lldb_protocol::mcp::Resource GetTargetResource(size_t target_idx, Target &target)
Definition Resource.cpp:78
static llvm::Expected< lldb_protocol::mcp::ReadResourceResult > ReadDebuggerResource(llvm::StringRef uri, lldb::user_id_t debugger_id)
Definition Resource.cpp:159
std::vector< lldb_protocol::mcp::Resource > GetResources() const override
Definition Resource.cpp:98
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
std::shared_ptr< lldb_private::Debugger > DebuggerSP
uint64_t user_id_t
Definition lldb-types.h:82
std::shared_ptr< lldb_private::Target > TargetSP
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:162
std::vector< TextResourceContents > contents
Definition Protocol.h:163
A known resource that the server is capable of reading.
Definition Protocol.h:109
std::string description
A description of what this resource represents.
Definition Protocol.h:117
std::string uri
The URI of this resource.
Definition Protocol.h:111
std::string mimeType
The MIME type of this resource, if known.
Definition Protocol.h:120
std::string name
A human-readable name for this resource.
Definition Protocol.h:114
The contents of a specific resource or sub-resource.
Definition Protocol.h:135
std::string text
The text of the item.
Definition Protocol.h:141
std::string uri
The URI of this resource.
Definition Protocol.h:137
std::string mimeType
The MIME type of this resource, if known.
Definition Protocol.h:144