brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.5 KiB · cf9b5a3 Raw
185 lines · cpp
1//===-- LocationsRequestHandler.cpp ---------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "DAP.h"10#include "EventHelper.h"11#include "JSONUtils.h"12#include "LLDBUtils.h"13#include "ProtocolUtils.h"14#include "RequestHandler.h"15#include "lldb/API/SBAddress.h"16#include "lldb/API/SBDeclaration.h"17#include "lldb/API/SBLineEntry.h"18 19namespace lldb_dap {20 21// "LocationsRequest": {22//   "allOf": [ { "$ref": "#/definitions/Request" }, {23//     "type": "object",24//     "description": "Looks up information about a location reference25//                     previously returned by the debug adapter.",26//     "properties": {27//       "command": {28//         "type": "string",29//         "enum": [ "locations" ]30//       },31//       "arguments": {32//         "$ref": "#/definitions/LocationsArguments"33//       }34//     },35//     "required": [ "command", "arguments" ]36//   }]37// },38// "LocationsArguments": {39//   "type": "object",40//   "description": "Arguments for `locations` request.",41//   "properties": {42//     "locationReference": {43//       "type": "integer",44//       "description": "Location reference to resolve."45//     }46//   },47//   "required": [ "locationReference" ]48// },49// "LocationsResponse": {50//   "allOf": [ { "$ref": "#/definitions/Response" }, {51//     "type": "object",52//     "description": "Response to `locations` request.",53//     "properties": {54//       "body": {55//         "type": "object",56//         "properties": {57//           "source": {58//             "$ref": "#/definitions/Source",59//             "description": "The source containing the location; either60//                             `source.path` or `source.sourceReference` must be61//                             specified."62//           },63//           "line": {64//             "type": "integer",65//             "description": "The line number of the location. The client66//                             capability `linesStartAt1` determines whether it67//                             is 0- or 1-based."68//           },69//           "column": {70//             "type": "integer",71//             "description": "Position of the location within the `line`. It is72//                             measured in UTF-16 code units and the client73//                             capability `columnsStartAt1` determines whether74//                             it is 0- or 1-based. If no column is given, the75//                             first position in the start line is assumed."76//           },77//           "endLine": {78//             "type": "integer",79//             "description": "End line of the location, present if the location80//                             refers to a range.  The client capability81//                             `linesStartAt1` determines whether it is 0- or82//                             1-based."83//           },84//           "endColumn": {85//             "type": "integer",86//             "description": "End position of the location within `endLine`,87//                             present if the location refers to a range. It is88//                             measured in UTF-16 code units and the client89//                             capability `columnsStartAt1` determines whether90//                             it is 0- or 1-based."91//           }92//         },93//         "required": [ "source", "line" ]94//       }95//     }96//   }]97// },98void LocationsRequestHandler::operator()(99    const llvm::json::Object &request) const {100  llvm::json::Object response;101  FillResponse(request, response);102  auto *arguments = request.getObject("arguments");103 104  const auto location_id =105      GetInteger<uint64_t>(arguments, "locationReference").value_or(0);106  // We use the lowest bit to distinguish between value location and declaration107  // location108  auto [var_ref, is_value_location] = UnpackLocation(location_id);109  lldb::SBValue variable = dap.variables.GetVariable(var_ref);110  if (!variable.IsValid()) {111    response["success"] = false;112    response["message"] = "Invalid variable reference";113    dap.SendJSON(llvm::json::Value(std::move(response)));114    return;115  }116 117  llvm::json::Object body;118  if (is_value_location) {119    // Get the value location120    if (!variable.GetType().IsPointerType() &&121        !variable.GetType().IsReferenceType()) {122      response["success"] = false;123      response["message"] =124          "Value locations are only available for pointers and references";125      dap.SendJSON(llvm::json::Value(std::move(response)));126      return;127    }128 129    lldb::addr_t raw_addr = variable.GetValueAsAddress();130    lldb::SBAddress addr = dap.target.ResolveLoadAddress(raw_addr);131    lldb::SBLineEntry line_entry = GetLineEntryForAddress(dap.target, addr);132 133    if (!line_entry.IsValid()) {134      response["success"] = false;135      response["message"] = "Failed to resolve line entry for location";136      dap.SendJSON(llvm::json::Value(std::move(response)));137      return;138    }139 140    const std::optional<protocol::Source> source =141        CreateSource(line_entry.GetFileSpec());142    if (!source) {143      response["success"] = false;144      response["message"] = "Failed to resolve file path for location";145      dap.SendJSON(llvm::json::Value(std::move(response)));146      return;147    }148 149    body.try_emplace("source", *source);150    if (int line = line_entry.GetLine())151      body.try_emplace("line", line);152    if (int column = line_entry.GetColumn())153      body.try_emplace("column", column);154  } else {155    // Get the declaration location156    lldb::SBDeclaration decl = variable.GetDeclaration();157    if (!decl.IsValid()) {158      response["success"] = false;159      response["message"] = "No declaration location available";160      dap.SendJSON(llvm::json::Value(std::move(response)));161      return;162    }163 164    const std::optional<protocol::Source> source =165        CreateSource(decl.GetFileSpec());166    if (!source) {167      response["success"] = false;168      response["message"] = "Failed to resolve file path for location";169      dap.SendJSON(llvm::json::Value(std::move(response)));170      return;171    }172 173    body.try_emplace("source", *source);174    if (int line = decl.GetLine())175      body.try_emplace("line", line);176    if (int column = decl.GetColumn())177      body.try_emplace("column", column);178  }179 180  response.try_emplace("body", std::move(body));181  dap.SendJSON(llvm::json::Value(std::move(response)));182}183 184} // namespace lldb_dap185