brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.1 KiB · ec26bb6 Raw
110 lines · cpp
1//===-- EvaluateRequestHandler.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 "Protocol/ProtocolRequests.h"14#include "Protocol/ProtocolTypes.h"15#include "RequestHandler.h"16#include "lldb/lldb-enumerations.h"17#include "llvm/ADT/StringRef.h"18#include "llvm/Support/Error.h"19 20using namespace llvm;21using namespace lldb_dap;22using namespace lldb_dap::protocol;23 24namespace lldb_dap {25 26/// Evaluates the given expression in the context of a stack frame.27///28/// The expression has access to any variables and arguments that are in scope.29Expected<EvaluateResponseBody>30EvaluateRequestHandler::Run(const EvaluateArguments &arguments) const {31  EvaluateResponseBody body;32  lldb::SBFrame frame = dap.GetLLDBFrame(arguments.frameId);33  std::string expression = arguments.expression;34  bool repeat_last_command =35      expression.empty() && dap.last_nonempty_var_expression.empty();36 37  if (arguments.context == protocol::eEvaluateContextRepl &&38      (repeat_last_command ||39       (!expression.empty() &&40        dap.DetectReplMode(frame, expression, false) == ReplMode::Command))) {41    // Since the current expression is not for a variable, clear the42    // last_nonempty_var_expression field.43    dap.last_nonempty_var_expression.clear();44    // If we're evaluating a command relative to the current frame, set the45    // focus_tid to the current frame for any thread related events.46    if (frame.IsValid()) {47      dap.focus_tid = frame.GetThread().GetThreadID();48    }49 50    bool required_command_failed = false;51    body.result = RunLLDBCommands(52        dap.debugger, llvm::StringRef(), {expression}, required_command_failed,53        /*parse_command_directives=*/false, /*echo_commands=*/false);54    return body;55  }56 57  if (arguments.context == eEvaluateContextRepl) {58    // If the expression is empty and the last expression was for a59    // variable, set the expression to the previous expression (repeat the60    // evaluation); otherwise save the current non-empty expression for the61    // next (possibly empty) variable expression.62    if (expression.empty())63      expression = dap.last_nonempty_var_expression;64    else65      dap.last_nonempty_var_expression = expression;66  }67 68  // Always try to get the answer from the local variables if possible. If69  // this fails, then if the context is not "hover", actually evaluate an70  // expression using the expression parser.71  //72  // "frame variable" is more reliable than the expression parser in73  // many cases and it is faster.74  lldb::SBValue value = frame.GetValueForVariablePath(75      expression.data(), lldb::eDynamicDontRunTarget);76 77  // Freeze dry the value in case users expand it later in the debug console78  if (value.GetError().Success() && arguments.context == eEvaluateContextRepl)79    value = value.Persist();80 81  if (value.GetError().Fail() && arguments.context != eEvaluateContextHover)82    value = frame.EvaluateExpression(expression.data());83 84  if (value.GetError().Fail())85    return ToError(value.GetError(), /*show_user=*/false);86 87  const bool hex = arguments.format ? arguments.format->hex : false;88 89  VariableDescription desc(value, dap.configuration.enableAutoVariableSummaries,90                           hex);91 92  body.result = desc.GetResult(arguments.context);93  body.type = desc.display_type_name;94 95  if (value.MightHaveChildren() || ValuePointsToCode(value))96    body.variablesReference = dap.variables.InsertVariable(97        value, /*is_permanent=*/arguments.context == eEvaluateContextRepl);98 99  if (lldb::addr_t addr = value.GetLoadAddress(); addr != LLDB_INVALID_ADDRESS)100    body.memoryReference = EncodeMemoryReference(addr);101 102  if (ValuePointsToCode(value) &&103      body.variablesReference != LLDB_DAP_INVALID_VAR_REF)104    body.valueLocationReference = PackLocation(body.variablesReference, true);105 106  return body;107}108 109} // namespace lldb_dap110