brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 5814245 Raw
220 lines · cpp
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-exception4//5//===----------------------------------------------------------------------===//6 7#include "Resource.h"8#include "lldb/Core/Debugger.h"9#include "lldb/Core/Module.h"10#include "lldb/Protocol/MCP/MCPError.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} // namespace55 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 68lldb_protocol::mcp::Resource69DebuggerResourceProvider::GetDebuggerResource(Debugger &debugger) {70  const lldb::user_id_t debugger_id = debugger.GetID();71 72  lldb_protocol::mcp::Resource resource;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 82lldb_protocol::mcp::Resource83DebuggerResourceProvider::GetTargetResource(size_t target_idx, Target &target) {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 91  lldb_protocol::mcp::Resource resource;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>103DebuggerResourceProvider::GetResources() const {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) {108    lldb::DebuggerSP debugger_sp = Debugger::GetDebuggerAtIndex(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>164DebuggerResourceProvider::ReadDebuggerResource(llvm::StringRef uri,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 175  lldb_protocol::mcp::TextResourceContents contents;176  contents.uri = uri;177  contents.mimeType = kMimeTypeJSON;178  contents.text = llvm::formatv("{0}", toJSON(debugger_resource));179 180  lldb_protocol::mcp::ReadResourceResult result;181  result.contents.push_back(contents);182  return result;183}184 185llvm::Expected<lldb_protocol::mcp::ReadResourceResult>186DebuggerResourceProvider::ReadTargetResource(llvm::StringRef uri,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 211  lldb_protocol::mcp::TextResourceContents contents;212  contents.uri = uri;213  contents.mimeType = kMimeTypeJSON;214  contents.text = llvm::formatv("{0}", toJSON(target_resource));215 216  lldb_protocol::mcp::ReadResourceResult result;217  result.contents.push_back(contents);218  return result;219}220