llvm-project/lldb/tools/lldb-dap/Handler/SourceRequestHandler.cpp
Ebuka Ezike 0b8a656ba1
[lldb-dap] Fix source references (#144364)
The
[protocol](https://microsoft.github.io/debug-adapter-protocol//specification.html#Types_Source)
expects that `sourceReference` be less than `(2^31)-1`, but we currently
represent memory address as source reference, this can be truncated
either when sending through json or by the client. Instead, generate new
source references based on the memory address.

Make the `ResolveSource` function return an optional source.
2025-06-26 18:22:47 +01:00

71 lines
2.4 KiB
C++

//===-- SourceRequestHandler.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "DAP.h"
#include "Handler/RequestHandler.h"
#include "LLDBUtils.h"
#include "Protocol/ProtocolRequests.h"
#include "Protocol/ProtocolTypes.h"
#include "lldb/API/SBAddress.h"
#include "lldb/API/SBExecutionContext.h"
#include "lldb/API/SBFrame.h"
#include "lldb/API/SBInstructionList.h"
#include "lldb/API/SBProcess.h"
#include "lldb/API/SBStream.h"
#include "lldb/API/SBSymbol.h"
#include "lldb/API/SBTarget.h"
#include "lldb/API/SBThread.h"
#include "lldb/lldb-types.h"
#include "llvm/Support/Error.h"
namespace lldb_dap {
/// Source request; value of command field is 'source'. The request retrieves
/// the source code for a given source reference.
llvm::Expected<protocol::SourceResponseBody>
SourceRequestHandler::Run(const protocol::SourceArguments &args) const {
uint32_t source_ref =
args.source->sourceReference.value_or(args.sourceReference);
const std::optional<lldb::addr_t> source_addr_opt =
dap.GetSourceReferenceAddress(source_ref);
if (!source_addr_opt)
return llvm::make_error<DAPError>(
llvm::formatv("Unknown source reference {}", source_ref));
lldb::SBAddress address(*source_addr_opt, dap.target);
if (!address.IsValid())
return llvm::make_error<DAPError>("source not found");
lldb::SBSymbol symbol = address.GetSymbol();
lldb::SBInstructionList insts;
if (symbol.IsValid()) {
insts = symbol.GetInstructions(dap.target);
} else {
// No valid symbol, just return the disassembly.
insts = dap.target.ReadInstructions(
address, dap.k_number_of_assembly_lines_for_nodebug);
}
if (!insts || insts.GetSize() == 0)
return llvm::make_error<DAPError>(
llvm::formatv("no instruction source for address {}",
address.GetLoadAddress(dap.target)));
lldb::SBStream stream;
lldb::SBExecutionContext exe_ctx(dap.target);
insts.GetDescription(stream, exe_ctx);
return protocol::SourceResponseBody{/*content=*/stream.GetData(),
/*mimeType=*/
"text/x-lldb.disassembly"};
}
} // namespace lldb_dap