Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Protocol/MCP/Resource.cpp
213845 views
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.1// See https://llvm.org/LICENSE.txt for license information.2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception3//4//===----------------------------------------------------------------------===//56#include "Resource.h"7#include "MCPError.h"8#include "lldb/Core/Debugger.h"9#include "lldb/Core/Module.h"10#include "lldb/Target/Platform.h"1112using namespace lldb_private::mcp;1314namespace {15struct DebuggerResource {16uint64_t debugger_id = 0;17std::string name;18uint64_t num_targets = 0;19};2021llvm::json::Value toJSON(const DebuggerResource &DR) {22llvm::json::Object Result{{"debugger_id", DR.debugger_id},23{"num_targets", DR.num_targets}};24if (!DR.name.empty())25Result.insert({"name", DR.name});26return Result;27}2829struct TargetResource {30size_t debugger_id = 0;31size_t target_idx = 0;32bool selected = false;33bool dummy = false;34std::string arch;35std::string path;36std::string platform;37};3839llvm::json::Value toJSON(const TargetResource &TR) {40llvm::json::Object Result{{"debugger_id", TR.debugger_id},41{"target_idx", TR.target_idx},42{"selected", TR.selected},43{"dummy", TR.dummy}};44if (!TR.arch.empty())45Result.insert({"arch", TR.arch});46if (!TR.path.empty())47Result.insert({"path", TR.path});48if (!TR.platform.empty())49Result.insert({"platform", TR.platform});50return Result;51}52} // namespace5354static constexpr llvm::StringLiteral kMimeTypeJSON = "application/json";5556template <typename... Args>57static llvm::Error createStringError(const char *format, Args &&...args) {58return llvm::createStringError(59llvm::formatv(format, std::forward<Args>(args)...).str());60}6162static llvm::Error createUnsupportedURIError(llvm::StringRef uri) {63return llvm::make_error<UnsupportedURI>(uri.str());64}6566protocol::Resource67DebuggerResourceProvider::GetDebuggerResource(Debugger &debugger) {68const lldb::user_id_t debugger_id = debugger.GetID();6970protocol::Resource resource;71resource.uri = llvm::formatv("lldb://debugger/{0}", debugger_id);72resource.name = debugger.GetInstanceName();73resource.description =74llvm::formatv("Information about debugger instance {0}: {1}", debugger_id,75debugger.GetInstanceName());76resource.mimeType = kMimeTypeJSON;77return resource;78}7980protocol::Resource81DebuggerResourceProvider::GetTargetResource(size_t target_idx, Target &target) {82const size_t debugger_id = target.GetDebugger().GetID();8384std::string target_name = llvm::formatv("target {0}", target_idx);8586if (Module *exe_module = target.GetExecutableModulePointer())87target_name = exe_module->GetFileSpec().GetFilename().GetString();8889protocol::Resource resource;90resource.uri =91llvm::formatv("lldb://debugger/{0}/target/{1}", debugger_id, target_idx);92resource.name = target_name;93resource.description =94llvm::formatv("Information about target {0} in debugger instance {1}",95target_idx, debugger_id);96resource.mimeType = kMimeTypeJSON;97return resource;98}99100std::vector<protocol::Resource> DebuggerResourceProvider::GetResources() const {101std::vector<protocol::Resource> resources;102103const size_t num_debuggers = Debugger::GetNumDebuggers();104for (size_t i = 0; i < num_debuggers; ++i) {105lldb::DebuggerSP debugger_sp = Debugger::GetDebuggerAtIndex(i);106if (!debugger_sp)107continue;108resources.emplace_back(GetDebuggerResource(*debugger_sp));109110TargetList &target_list = debugger_sp->GetTargetList();111const size_t num_targets = target_list.GetNumTargets();112for (size_t j = 0; j < num_targets; ++j) {113lldb::TargetSP target_sp = target_list.GetTargetAtIndex(j);114if (!target_sp)115continue;116resources.emplace_back(GetTargetResource(j, *target_sp));117}118}119120return resources;121}122123llvm::Expected<protocol::ResourceResult>124DebuggerResourceProvider::ReadResource(llvm::StringRef uri) const {125126auto [protocol, path] = uri.split("://");127128if (protocol != "lldb")129return createUnsupportedURIError(uri);130131llvm::SmallVector<llvm::StringRef, 4> components;132path.split(components, '/');133134if (components.size() < 2)135return createUnsupportedURIError(uri);136137if (components[0] != "debugger")138return createUnsupportedURIError(uri);139140size_t debugger_idx;141if (components[1].getAsInteger(0, debugger_idx))142return createStringError("invalid debugger id '{0}': {1}", components[1],143path);144145if (components.size() > 3) {146if (components[2] != "target")147return createUnsupportedURIError(uri);148149size_t target_idx;150if (components[3].getAsInteger(0, target_idx))151return createStringError("invalid target id '{0}': {1}", components[3],152path);153154return ReadTargetResource(uri, debugger_idx, target_idx);155}156157return ReadDebuggerResource(uri, debugger_idx);158}159160llvm::Expected<protocol::ResourceResult>161DebuggerResourceProvider::ReadDebuggerResource(llvm::StringRef uri,162lldb::user_id_t debugger_id) {163lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);164if (!debugger_sp)165return createStringError("invalid debugger id: {0}", debugger_id);166167DebuggerResource debugger_resource;168debugger_resource.debugger_id = debugger_id;169debugger_resource.name = debugger_sp->GetInstanceName();170debugger_resource.num_targets = debugger_sp->GetTargetList().GetNumTargets();171172protocol::ResourceContents contents;173contents.uri = uri;174contents.mimeType = kMimeTypeJSON;175contents.text = llvm::formatv("{0}", toJSON(debugger_resource));176177protocol::ResourceResult result;178result.contents.push_back(contents);179return result;180}181182llvm::Expected<protocol::ResourceResult>183DebuggerResourceProvider::ReadTargetResource(llvm::StringRef uri,184lldb::user_id_t debugger_id,185size_t target_idx) {186187lldb::DebuggerSP debugger_sp = Debugger::FindDebuggerWithID(debugger_id);188if (!debugger_sp)189return createStringError("invalid debugger id: {0}", debugger_id);190191TargetList &target_list = debugger_sp->GetTargetList();192lldb::TargetSP target_sp = target_list.GetTargetAtIndex(target_idx);193if (!target_sp)194return createStringError("invalid target idx: {0}", target_idx);195196TargetResource target_resource;197target_resource.debugger_id = debugger_id;198target_resource.target_idx = target_idx;199target_resource.arch = target_sp->GetArchitecture().GetTriple().str();200target_resource.dummy = target_sp->IsDummyTarget();201target_resource.selected = target_sp == debugger_sp->GetSelectedTarget();202203if (Module *exe_module = target_sp->GetExecutableModulePointer())204target_resource.path = exe_module->GetFileSpec().GetPath();205if (lldb::PlatformSP platform_sp = target_sp->GetPlatform())206target_resource.platform = platform_sp->GetName();207208protocol::ResourceContents contents;209contents.uri = uri;210contents.mimeType = kMimeTypeJSON;211contents.text = llvm::formatv("{0}", toJSON(target_resource));212213protocol::ResourceResult result;214result.contents.push_back(contents);215return result;216}217218219