brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.3 KiB · 9295b6c Raw
92 lines · cpp
1//===-- StepInTargetsRequestHandler.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 "Protocol/ProtocolRequests.h"11#include "RequestHandler.h"12#include "lldb/API/SBInstruction.h"13#include "lldb/lldb-defines.h"14 15using namespace lldb_dap::protocol;16namespace lldb_dap {17 18// This request retrieves the possible step-in targets for the specified stack19// frame.20// These targets can be used in the `stepIn` request.21// Clients should only call this request if the corresponding capability22// `supportsStepInTargetsRequest` is true.23llvm::Expected<StepInTargetsResponseBody>24StepInTargetsRequestHandler::Run(const StepInTargetsArguments &args) const {25  dap.step_in_targets.clear();26  const lldb::SBFrame frame = dap.GetLLDBFrame(args.frameId);27  if (!frame.IsValid())28    return llvm::make_error<DAPError>("Failed to get frame for input frameId.");29 30  lldb::SBAddress pc_addr = frame.GetPCAddress();31  lldb::SBAddress line_end_addr =32      pc_addr.GetLineEntry().GetSameLineContiguousAddressRangeEnd(true);33  lldb::SBInstructionList insts = dap.target.ReadInstructions(34      pc_addr, line_end_addr, /*flavor_string=*/nullptr);35 36  if (!insts.IsValid())37    return llvm::make_error<DAPError>("Failed to get instructions for frame.");38 39  StepInTargetsResponseBody body;40  const size_t num_insts = insts.GetSize();41  for (size_t i = 0; i < num_insts; ++i) {42    lldb::SBInstruction inst = insts.GetInstructionAtIndex(i);43    if (!inst.IsValid())44      break;45 46    const lldb::addr_t inst_addr = inst.GetAddress().GetLoadAddress(dap.target);47    if (inst_addr == LLDB_INVALID_ADDRESS)48      break;49 50    // Note: currently only x86/x64 supports flow kind.51    const lldb::InstructionControlFlowKind flow_kind =52        inst.GetControlFlowKind(dap.target);53 54    if (flow_kind == lldb::eInstructionControlFlowKindCall) {55 56      const llvm::StringRef call_operand_name = inst.GetOperands(dap.target);57      lldb::addr_t call_target_addr = LLDB_INVALID_ADDRESS;58      if (call_operand_name.getAsInteger(0, call_target_addr))59        continue;60 61      const lldb::SBAddress call_target_load_addr =62          dap.target.ResolveLoadAddress(call_target_addr);63      if (!call_target_load_addr.IsValid())64        continue;65 66      // The existing ThreadPlanStepInRange only accept step in target67      // function with debug info.68      lldb::SBSymbolContext sc = dap.target.ResolveSymbolContextForAddress(69          call_target_load_addr, lldb::eSymbolContextFunction);70 71      // The existing ThreadPlanStepInRange only accept step in target72      // function with debug info.73      llvm::StringRef step_in_target_name;74      if (sc.IsValid() && sc.GetFunction().IsValid())75        step_in_target_name = sc.GetFunction().GetDisplayName();76 77      // Skip call sites if we fail to resolve its symbol name.78      if (step_in_target_name.empty())79        continue;80 81      StepInTarget target;82      target.id = inst_addr;83      target.label = step_in_target_name;84      dap.step_in_targets.try_emplace(inst_addr, step_in_target_name);85      body.targets.emplace_back(std::move(target));86    }87  }88  return body;89}90 91} // namespace lldb_dap92