summaryrefslogtreecommitdiff
path: root/lldb/include
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/include')
-rw-r--r--lldb/include/lldb/API/SBFrame.h2
-rw-r--r--lldb/include/lldb/API/SBFunction.h2
-rw-r--r--lldb/include/lldb/API/SBSymbol.h2
-rw-r--r--lldb/include/lldb/API/SBSymbolContext.h1
-rw-r--r--lldb/include/lldb/Core/Architecture.h9
-rw-r--r--lldb/include/lldb/Core/Disassembler.h38
-rw-r--r--lldb/include/lldb/Core/FormatEntity.h1
-rw-r--r--lldb/include/lldb/Core/Mangled.h11
-rw-r--r--lldb/include/lldb/Core/Opcode.h2
-rw-r--r--lldb/include/lldb/Core/ProtocolServer.h2
-rw-r--r--lldb/include/lldb/Expression/DWARFExpression.h3
-rw-r--r--lldb/include/lldb/Expression/Expression.h8
-rw-r--r--lldb/include/lldb/Expression/IRMemoryMap.h2
-rw-r--r--lldb/include/lldb/Host/File.h16
-rw-r--r--lldb/include/lldb/Host/HostInfoBase.h14
-rw-r--r--lldb/include/lldb/Host/JSONTransport.h11
-rw-r--r--lldb/include/lldb/Host/macosx/HostInfoMacOSX.h3
-rw-r--r--lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h55
-rw-r--r--lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h10
-rw-r--r--lldb/include/lldb/Interpreter/Options.h4
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h5
-rw-r--r--lldb/include/lldb/Protocol/MCP/Protocol.h240
-rw-r--r--lldb/include/lldb/Protocol/MCP/Resource.h2
-rw-r--r--lldb/include/lldb/Protocol/MCP/Server.h82
-rw-r--r--lldb/include/lldb/Protocol/MCP/Tool.h3
-rw-r--r--lldb/include/lldb/Protocol/MCP/Transport.h48
-rw-r--r--lldb/include/lldb/Symbol/SymbolFile.h17
-rw-r--r--lldb/include/lldb/Target/CoreFileMemoryRanges.h2
-rw-r--r--lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h3
-rw-r--r--lldb/include/lldb/Target/RegisterContextUnwind.h45
-rw-r--r--lldb/include/lldb/Target/StackFrame.h51
-rw-r--r--lldb/include/lldb/Target/StackFrameList.h12
-rw-r--r--lldb/include/lldb/Target/StackID.h50
-rw-r--r--lldb/include/lldb/Target/Statistics.h22
-rw-r--r--lldb/include/lldb/Target/StopInfo.h6
-rw-r--r--lldb/include/lldb/Target/Thread.h5
-rw-r--r--lldb/include/lldb/Target/UnwindLLDB.h2
-rw-r--r--lldb/include/lldb/Utility/AnsiTerminal.h5
-rw-r--r--lldb/include/lldb/ValueObject/DILAST.h52
-rw-r--r--lldb/include/lldb/ValueObject/DILEval.h9
-rw-r--r--lldb/include/lldb/ValueObject/DILLexer.h4
-rw-r--r--lldb/include/lldb/ValueObject/DILParser.h3
-rw-r--r--lldb/include/lldb/lldb-forward.h3
43 files changed, 673 insertions, 194 deletions
diff --git a/lldb/include/lldb/API/SBFrame.h b/lldb/include/lldb/API/SBFrame.h
index 08de0605b324..e4bbcd5ddcd9 100644
--- a/lldb/include/lldb/API/SBFrame.h
+++ b/lldb/include/lldb/API/SBFrame.h
@@ -104,6 +104,8 @@ public:
bool IsArtificial() const;
+ bool IsSynthetic() const;
+
/// Return whether a frame recognizer decided this frame should not
/// be displayes in backtraces etc.
bool IsHidden() const;
diff --git a/lldb/include/lldb/API/SBFunction.h b/lldb/include/lldb/API/SBFunction.h
index 0a8aeeff1ea5..e703ae5dd63c 100644
--- a/lldb/include/lldb/API/SBFunction.h
+++ b/lldb/include/lldb/API/SBFunction.h
@@ -36,6 +36,8 @@ public:
const char *GetMangledName() const;
+ const char *GetBaseName() const;
+
lldb::SBInstructionList GetInstructions(lldb::SBTarget target);
lldb::SBInstructionList GetInstructions(lldb::SBTarget target,
diff --git a/lldb/include/lldb/API/SBSymbol.h b/lldb/include/lldb/API/SBSymbol.h
index a93bc7a7ae07..580458ede212 100644
--- a/lldb/include/lldb/API/SBSymbol.h
+++ b/lldb/include/lldb/API/SBSymbol.h
@@ -36,6 +36,8 @@ public:
const char *GetMangledName() const;
+ const char *GetBaseName() const;
+
lldb::SBInstructionList GetInstructions(lldb::SBTarget target);
lldb::SBInstructionList GetInstructions(lldb::SBTarget target,
diff --git a/lldb/include/lldb/API/SBSymbolContext.h b/lldb/include/lldb/API/SBSymbolContext.h
index 128b0b65b786..19f29c629d09 100644
--- a/lldb/include/lldb/API/SBSymbolContext.h
+++ b/lldb/include/lldb/API/SBSymbolContext.h
@@ -66,6 +66,7 @@ protected:
friend class SBTarget;
friend class SBSymbolContextList;
+ friend class lldb_private::ScriptInterpreter;
friend class lldb_private::python::SWIGBridge;
SBSymbolContext(const lldb_private::SymbolContext &sc_ptr);
diff --git a/lldb/include/lldb/Core/Architecture.h b/lldb/include/lldb/Core/Architecture.h
index b6fc1a20e1e6..ed64a895717a 100644
--- a/lldb/include/lldb/Core/Architecture.h
+++ b/lldb/include/lldb/Core/Architecture.h
@@ -12,6 +12,7 @@
#include "lldb/Core/PluginInterface.h"
#include "lldb/Target/DynamicRegisterInfo.h"
#include "lldb/Target/MemoryTagManager.h"
+#include "lldb/Target/RegisterContextUnwind.h"
namespace lldb_private {
@@ -129,6 +130,14 @@ public:
RegisterContext &reg_context) const {
return false;
}
+
+ /// Return an UnwindPlan that allows architecture-defined rules for finding
+ /// saved registers, given a particular set of register values.
+ virtual lldb::UnwindPlanSP GetArchitectureUnwindPlan(
+ lldb_private::Thread &thread, lldb_private::RegisterContextUnwind *regctx,
+ std::shared_ptr<const UnwindPlan> current_unwindplan) {
+ return lldb::UnwindPlanSP();
+ }
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h
index 50a5d8783584..db186dd33d77 100644
--- a/lldb/include/lldb/Core/Disassembler.h
+++ b/lldb/include/lldb/Core/Disassembler.h
@@ -169,7 +169,7 @@ public:
virtual bool IsAuthenticated() = 0;
- bool CanSetBreakpoint ();
+ bool CanSetBreakpoint();
virtual size_t Decode(const Disassembler &disassembler,
const DataExtractor &data,
@@ -282,7 +282,7 @@ std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm);
std::function<bool(const Instruction::Operand &)>
MatchOpType(Instruction::Operand::Type type);
-}
+} // namespace OperandMatchers
class InstructionList {
public:
@@ -316,20 +316,19 @@ public:
/// @param[in] ignore_calls
/// It true, then fine the first branch instruction that isn't
/// a function call (a branch that calls and returns to the next
- /// instruction). If false, find the instruction index of any
+ /// instruction). If false, find the instruction index of any
/// branch in the list.
- ///
+ ///
/// @param[out] found_calls
- /// If non-null, this will be set to true if any calls were found in
+ /// If non-null, this will be set to true if any calls were found in
/// extending the range.
- ///
+ ///
/// @return
/// The instruction index of the first branch that is at or past
- /// \a start. Returns UINT32_MAX if no matching branches are
+ /// \a start. Returns UINT32_MAX if no matching branches are
/// found.
//------------------------------------------------------------------
- uint32_t GetIndexOfNextBranchInstruction(uint32_t start,
- bool ignore_calls,
+ uint32_t GetIndexOfNextBranchInstruction(uint32_t start, bool ignore_calls,
bool *found_calls) const;
uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,
@@ -399,6 +398,7 @@ public:
eOptionMarkPCAddress =
(1u << 3), // Mark the disassembly line the contains the PC
eOptionShowControlFlowKind = (1u << 4),
+ eOptionVariableAnnotations = (1u << 5),
};
enum HexImmediateStyle {
@@ -566,6 +566,26 @@ private:
const Disassembler &operator=(const Disassembler &) = delete;
};
+/// Tracks live variable annotations across instructions and produces
+/// per-instruction "events" like `name = RDI` or `name = <undef>`.
+class VariableAnnotator {
+ struct VarState {
+ /// Display name.
+ std::string name;
+ /// Last printed location (empty means <undef>).
+ std::string last_loc;
+ };
+
+ // Live state from the previous instruction, keyed by Variable::GetID().
+ llvm::DenseMap<lldb::user_id_t, VarState> Live_;
+
+public:
+ /// Compute annotation strings for a single instruction and update `Live_`.
+ /// Returns only the events that should be printed *at this instruction*.
+ std::vector<std::string> annotate(Instruction &inst, Target &target,
+ const lldb::ModuleSP &module_sp);
+};
+
} // namespace lldb_private
#endif // LLDB_CORE_DISASSEMBLER_H
diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h
index d602edffb4c8..40916dc48a70 100644
--- a/lldb/include/lldb/Core/FormatEntity.h
+++ b/lldb/include/lldb/Core/FormatEntity.h
@@ -80,6 +80,7 @@ struct Entry {
FrameRegisterFlags,
FrameRegisterByName,
FrameIsArtificial,
+ FrameKind,
ScriptFrame,
FunctionID,
FunctionDidChange,
diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h
index eb9a58c56889..47f1c6a8d80b 100644
--- a/lldb/include/lldb/Core/Mangled.h
+++ b/lldb/include/lldb/Core/Mangled.h
@@ -287,6 +287,17 @@ public:
/// Retrieve \c DemangledNameInfo of the demangled name held by this object.
const std::optional<DemangledNameInfo> &GetDemangledInfo() const;
+ /// Compute the base name (without namespace/class qualifiers) from the
+ /// demangled name.
+ ///
+ /// For a demangled name like "ns::MyClass<int>::templateFunc", this returns
+ /// just "templateFunc".
+ ///
+ /// \return
+ /// A ConstString containing the basename, or nullptr if computation
+ /// fails.
+ ConstString GetBaseName() const;
+
private:
/// If \c force is \c false, this function will re-use the previously
/// demangled name (if any). If \c force is \c true (or the mangled name
diff --git a/lldb/include/lldb/Core/Opcode.h b/lldb/include/lldb/Core/Opcode.h
index f680e0b91ab8..7bbd73d039f9 100644
--- a/lldb/include/lldb/Core/Opcode.h
+++ b/lldb/include/lldb/Core/Opcode.h
@@ -211,7 +211,7 @@ public:
if (bytes != nullptr && length > 0) {
m_type = type;
m_data.inst.length = length;
- assert(length < sizeof(m_data.inst.bytes));
+ assert(length <= sizeof(m_data.inst.bytes));
memcpy(m_data.inst.bytes, bytes, length);
m_byte_order = order;
} else {
diff --git a/lldb/include/lldb/Core/ProtocolServer.h b/lldb/include/lldb/Core/ProtocolServer.h
index 937256c10aec..fcb91ea203e1 100644
--- a/lldb/include/lldb/Core/ProtocolServer.h
+++ b/lldb/include/lldb/Core/ProtocolServer.h
@@ -22,6 +22,8 @@ public:
static ProtocolServer *GetOrCreate(llvm::StringRef name);
+ static llvm::Error Terminate();
+
static std::vector<llvm::StringRef> GetSupportedProtocols();
struct Connection {
diff --git a/lldb/include/lldb/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h
index 8fcc5d37b91c..1f8464cf5cf8 100644
--- a/lldb/include/lldb/Expression/DWARFExpression.h
+++ b/lldb/include/lldb/Expression/DWARFExpression.h
@@ -159,7 +159,8 @@ public:
return data.GetByteSize() > 0;
}
- void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
+ void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi,
+ llvm::DIDumpOptions options = {}) const;
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const;
diff --git a/lldb/include/lldb/Expression/Expression.h b/lldb/include/lldb/Expression/Expression.h
index 20067f469895..847226167d58 100644
--- a/lldb/include/lldb/Expression/Expression.h
+++ b/lldb/include/lldb/Expression/Expression.h
@@ -103,11 +103,15 @@ protected:
///
/// The format being:
///
-/// <prefix>:<module uid>:<symbol uid>:<name>
+/// <prefix>:<discriminator>:<module uid>:<symbol uid>:<name>
///
/// The label string needs to stay valid for the entire lifetime
/// of this object.
struct FunctionCallLabel {
+ /// Arbitrary string which language plugins can interpret for their
+ /// own needs.
+ llvm::StringRef discriminator;
+
/// Unique identifier of the lldb_private::Module
/// which contains the symbol identified by \c symbol_id.
lldb::user_id_t module_id;
@@ -133,7 +137,7 @@ struct FunctionCallLabel {
///
/// The representation roundtrips through \c fromString:
/// \code{.cpp}
- /// llvm::StringRef encoded = "$__lldb_func:0x0:0x0:_Z3foov";
+ /// llvm::StringRef encoded = "$__lldb_func:blah:0x0:0x0:_Z3foov";
/// FunctionCallLabel label = *fromString(label);
///
/// assert (label.toString() == encoded);
diff --git a/lldb/include/lldb/Expression/IRMemoryMap.h b/lldb/include/lldb/Expression/IRMemoryMap.h
index 58b95c56c1c3..56f79444764e 100644
--- a/lldb/include/lldb/Expression/IRMemoryMap.h
+++ b/lldb/include/lldb/Expression/IRMemoryMap.h
@@ -65,7 +65,7 @@ public:
size_t size, Status &error);
void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar,
size_t size, Status &error);
- void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address,
+ void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t pointer,
Status &error);
void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size,
Status &error);
diff --git a/lldb/include/lldb/Host/File.h b/lldb/include/lldb/Host/File.h
index 9e2d0abe0b1a..7402a2231735 100644
--- a/lldb/include/lldb/Host/File.h
+++ b/lldb/include/lldb/Host/File.h
@@ -382,15 +382,11 @@ public:
Unowned = false,
};
- NativeFile() : m_descriptor(kInvalidDescriptor), m_stream(kInvalidStream) {}
+ NativeFile();
- NativeFile(FILE *fh, bool transfer_ownership)
- : m_descriptor(kInvalidDescriptor), m_own_descriptor(false), m_stream(fh),
- m_options(), m_own_stream(transfer_ownership) {}
+ NativeFile(FILE *fh, bool transfer_ownership);
- NativeFile(int fd, OpenOptions options, bool transfer_ownership)
- : m_descriptor(fd), m_own_descriptor(transfer_ownership),
- m_stream(kInvalidStream), m_options(options), m_own_stream(false) {}
+ NativeFile(int fd, OpenOptions options, bool transfer_ownership);
~NativeFile() override { Close(); }
@@ -444,17 +440,19 @@ protected:
return ValueGuard(m_stream_mutex, StreamIsValidUnlocked());
}
- int m_descriptor;
+ int m_descriptor = kInvalidDescriptor;
bool m_own_descriptor = false;
mutable std::mutex m_descriptor_mutex;
- FILE *m_stream;
+ FILE *m_stream = kInvalidStream;
mutable std::mutex m_stream_mutex;
OpenOptions m_options{};
bool m_own_stream = false;
std::mutex offset_access_mutex;
+ bool is_windows_console = false;
+
private:
NativeFile(const NativeFile &) = delete;
const NativeFile &operator=(const NativeFile &) = delete;
diff --git a/lldb/include/lldb/Host/HostInfoBase.h b/lldb/include/lldb/Host/HostInfoBase.h
index b6a95fffb2db..a6aaacd9d6fe 100644
--- a/lldb/include/lldb/Host/HostInfoBase.h
+++ b/lldb/include/lldb/Host/HostInfoBase.h
@@ -102,11 +102,19 @@ public:
/// member of the FileSpec is filled in.
static FileSpec GetSystemPluginDir();
+ /// Returns the directory containing the users home (e.g. `~/`). Only the
+ /// directory member of the FileSpec is filled in.
+ static FileSpec GetUserHomeDir();
+
+ /// Returns the directory containing the users lldb home (e.g. `~/.lldb/`).
+ /// Only the directory member of the FileSpec is filled in.
+ static FileSpec GetUserLLDBDir();
+
/// Returns the directory containing the user plugins. Only the directory
/// member of the FileSpec is filled in.
static FileSpec GetUserPluginDir();
- /// Returns the proces temporary directory. This directory will be cleaned up
+ /// Returns the process temporary directory. This directory will be cleaned up
/// when this process exits. Only the directory member of the FileSpec is
/// filled in.
static FileSpec GetProcessTempDir();
@@ -167,11 +175,13 @@ protected:
static bool ComputeTempFileBaseDirectory(FileSpec &file_spec);
static bool ComputeHeaderDirectory(FileSpec &file_spec);
static bool ComputeSystemPluginsDirectory(FileSpec &file_spec);
+ static bool ComputeUserHomeDirectory(FileSpec &file_spec);
+ static bool ComputeUserLLDBHomeDirectory(FileSpec &file_spec);
static bool ComputeUserPluginsDirectory(FileSpec &file_spec);
static void ComputeHostArchitectureSupport(ArchSpec &arch_32,
ArchSpec &arch_64);
};
-}
+} // namespace lldb_private
#endif
diff --git a/lldb/include/lldb/Host/JSONTransport.h b/lldb/include/lldb/Host/JSONTransport.h
index 0be60a8f3f96..210f33edace6 100644
--- a/lldb/include/lldb/Host/JSONTransport.h
+++ b/lldb/include/lldb/Host/JSONTransport.h
@@ -100,7 +100,8 @@ public:
virtual llvm::Expected<MainLoop::ReadHandleUP>
RegisterMessageHandler(MainLoop &loop, MessageHandler &handler) = 0;
-protected:
+ // FIXME: Refactor mcp::Server to not directly access log on the transport.
+ // protected:
template <typename... Ts> inline auto Logv(const char *Fmt, Ts &&...Vals) {
Log(llvm::formatv(Fmt, std::forward<Ts>(Vals)...).str());
}
@@ -139,9 +140,7 @@ public:
/// detail.
static constexpr size_t kReadBufferSize = 1024;
-protected:
- virtual llvm::Expected<std::vector<std::string>> Parse() = 0;
- virtual std::string Encode(const llvm::json::Value &message) = 0;
+ // FIXME: Write should be protected.
llvm::Error Write(const llvm::json::Value &message) {
this->Logv("<-- {0}", message);
std::string output = Encode(message);
@@ -149,6 +148,10 @@ protected:
return m_out->Write(output.data(), bytes_written).takeError();
}
+protected:
+ virtual llvm::Expected<std::vector<std::string>> Parse() = 0;
+ virtual std::string Encode(const llvm::json::Value &message) = 0;
+
llvm::SmallString<kReadBufferSize> m_buffer;
private:
diff --git a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
index d04841885660..734a394c1867 100644
--- a/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
+++ b/lldb/include/lldb/Host/macosx/HostInfoMacOSX.h
@@ -56,6 +56,7 @@ protected:
static std::string FindComponentInPath(llvm::StringRef path,
llvm::StringRef component);
};
-}
+
+} // namespace lldb_private
#endif
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h
new file mode 100644
index 000000000000..8ef4b37d6ba1
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedFrameInterface.h
@@ -0,0 +1,55 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEINTERFACE_H
+
+#include "ScriptedInterface.h"
+#include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/lldb-private.h"
+#include <optional>
+#include <string>
+
+namespace lldb_private {
+class ScriptedFrameInterface : virtual public ScriptedInterface {
+public:
+ virtual llvm::Expected<StructuredData::GenericSP>
+ CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx,
+ StructuredData::DictionarySP args_sp,
+ StructuredData::Generic *script_obj = nullptr) = 0;
+
+ virtual lldb::user_id_t GetID() { return LLDB_INVALID_FRAME_ID; }
+
+ virtual lldb::addr_t GetPC() { return LLDB_INVALID_ADDRESS; }
+
+ virtual std::optional<SymbolContext> GetSymbolContext() {
+ return std::nullopt;
+ }
+
+ virtual std::optional<std::string> GetFunctionName() { return std::nullopt; }
+
+ virtual std::optional<std::string> GetDisplayFunctionName() {
+ return std::nullopt;
+ }
+
+ virtual bool IsInlined() { return false; }
+
+ virtual bool IsArtificial() { return false; }
+
+ virtual bool IsHidden() { return false; }
+
+ virtual StructuredData::DictionarySP GetRegisterInfo() { return {}; }
+
+ virtual std::optional<std::string> GetRegisterContext() {
+ return std::nullopt;
+ }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDFRAMEINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
index a7cfc690b67d..bc58f344d36f 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedThreadInterface.h
@@ -44,6 +44,16 @@ public:
}
virtual StructuredData::ArraySP GetExtendedInfo() { return {}; }
+
+ virtual std::optional<std::string> GetScriptedFramePluginName() {
+ return std::nullopt;
+ }
+
+protected:
+ friend class ScriptedFrame;
+ virtual lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() {
+ return {};
+ }
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h
index 864bda6f24c8..2d06605f5f0b 100644
--- a/lldb/include/lldb/Interpreter/Options.h
+++ b/lldb/include/lldb/Interpreter/Options.h
@@ -85,10 +85,10 @@ public:
void OutputFormattedUsageText(Stream &strm,
const OptionDefinition &option_def,
- uint32_t output_max_columns);
+ uint32_t output_max_columns, bool use_color);
void GenerateOptionUsage(Stream &strm, CommandObject &cmd,
- uint32_t screen_width);
+ uint32_t screen_width, bool use_color);
bool SupportsLongOption(const char *long_option);
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index dffb9b82abf3..024bbc90a9a3 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -26,6 +26,7 @@
#include "lldb/Host/PseudoTerminal.h"
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/Interfaces/OperatingSystemInterface.h"
+#include "lldb/Interpreter/Interfaces/ScriptedFrameInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedPlatformInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
@@ -531,6 +532,10 @@ public:
return {};
}
+ virtual lldb::ScriptedFrameInterfaceSP CreateScriptedFrameInterface() {
+ return {};
+ }
+
virtual lldb::ScriptedThreadPlanInterfaceSP
CreateScriptedThreadPlanInterface() {
return {};
diff --git a/lldb/include/lldb/Protocol/MCP/Protocol.h b/lldb/include/lldb/Protocol/MCP/Protocol.h
index 49f949022175..6e1ffcbe1f3e 100644
--- a/lldb/include/lldb/Protocol/MCP/Protocol.h
+++ b/lldb/include/lldb/Protocol/MCP/Protocol.h
@@ -18,6 +18,7 @@
#include <optional>
#include <string>
#include <variant>
+#include <vector>
namespace lldb_protocol::mcp {
@@ -38,11 +39,24 @@ struct Request {
/// The method's params.
std::optional<llvm::json::Value> params;
};
-
llvm::json::Value toJSON(const Request &);
bool fromJSON(const llvm::json::Value &, Request &, llvm::json::Path);
bool operator==(const Request &, const Request &);
+enum ErrorCode : signed {
+ /// Invalid JSON was received by the server. An error occurred on the server
+ /// while parsing the JSON text.
+ eErrorCodeParseError = -32700,
+ /// The JSON sent is not a valid Request object.
+ eErrorCodeInvalidRequest = -32600,
+ /// The method does not exist / is not available.
+ eErrorCodeMethodNotFound = -32601,
+ /// Invalid method parameter(s).
+ eErrorCodeInvalidParams = -32602,
+ /// Internal JSON-RPC error.
+ eErrorCodeInternalError = -32603,
+};
+
struct Error {
/// The error type that occurred.
int64_t code = 0;
@@ -52,9 +66,8 @@ struct Error {
/// Additional information about the error. The value of this member is
/// defined by the sender (e.g. detailed error information, nested errors
/// etc.).
- std::optional<llvm::json::Value> data;
+ std::optional<llvm::json::Value> data = std::nullopt;
};
-
llvm::json::Value toJSON(const Error &);
bool fromJSON(const llvm::json::Value &, Error &, llvm::json::Path);
bool operator==(const Error &, const Error &);
@@ -67,7 +80,6 @@ struct Response {
/// response.
std::variant<Error, llvm::json::Value> result;
};
-
llvm::json::Value toJSON(const Response &);
bool fromJSON(const llvm::json::Value &, Response &, llvm::json::Path);
bool operator==(const Response &, const Response &);
@@ -79,7 +91,6 @@ struct Notification {
/// The notification's params.
std::optional<llvm::json::Value> params;
};
-
llvm::json::Value toJSON(const Notification &);
bool fromJSON(const llvm::json::Value &, Notification &, llvm::json::Path);
bool operator==(const Notification &, const Notification &);
@@ -90,45 +101,9 @@ using Message = std::variant<Request, Response, Notification>;
// not force it to be checked early here.
static_assert(std::is_convertible_v<Message, Message>,
"Message is not convertible to itself");
-
bool fromJSON(const llvm::json::Value &, Message &, llvm::json::Path);
llvm::json::Value toJSON(const Message &);
-struct ToolCapability {
- /// Whether this server supports notifications for changes to the tool list.
- bool listChanged = false;
-};
-
-llvm::json::Value toJSON(const ToolCapability &);
-bool fromJSON(const llvm::json::Value &, ToolCapability &, llvm::json::Path);
-
-struct ResourceCapability {
- /// Whether this server supports notifications for changes to the resources
- /// list.
- bool listChanged = false;
-
- /// Whether subscriptions are supported.
- bool subscribe = false;
-};
-
-llvm::json::Value toJSON(const ResourceCapability &);
-bool fromJSON(const llvm::json::Value &, ResourceCapability &,
- llvm::json::Path);
-
-/// Capabilities that a server may support. Known capabilities are defined here,
-/// in this schema, but this is not a closed set: any server can define its own,
-/// additional capabilities.
-struct Capabilities {
- /// Tool capabilities of the server.
- ToolCapability tools;
-
- /// Resource capabilities of the server.
- ResourceCapability resources;
-};
-
-llvm::json::Value toJSON(const Capabilities &);
-bool fromJSON(const llvm::json::Value &, Capabilities &, llvm::json::Path);
-
/// A known resource that the server is capable of reading.
struct Resource {
/// The URI of this resource.
@@ -138,17 +113,25 @@ struct Resource {
std::string name;
/// A description of what this resource represents.
- std::string description;
+ std::string description = "";
/// The MIME type of this resource, if known.
- std::string mimeType;
+ std::string mimeType = "";
};
llvm::json::Value toJSON(const Resource &);
bool fromJSON(const llvm::json::Value &, Resource &, llvm::json::Path);
+/// The server’s response to a resources/list request from the client.
+struct ListResourcesResult {
+ std::vector<Resource> resources;
+};
+llvm::json::Value toJSON(const ListResourcesResult &);
+bool fromJSON(const llvm::json::Value &, ListResourcesResult &,
+ llvm::json::Path);
+
/// The contents of a specific resource or sub-resource.
-struct ResourceContents {
+struct TextResourceContents {
/// The URI of this resource.
std::string uri;
@@ -160,34 +143,37 @@ struct ResourceContents {
std::string mimeType;
};
-llvm::json::Value toJSON(const ResourceContents &);
-bool fromJSON(const llvm::json::Value &, ResourceContents &, llvm::json::Path);
+llvm::json::Value toJSON(const TextResourceContents &);
+bool fromJSON(const llvm::json::Value &, TextResourceContents &,
+ llvm::json::Path);
-/// The server's response to a resources/read request from the client.
-struct ResourceResult {
- std::vector<ResourceContents> contents;
+/// Sent from the client to the server, to read a specific resource URI.
+struct ReadResourceParams {
+ /// The URI of the resource to read. The URI can use any protocol; it is up to
+ /// the server how to interpret it.
+ std::string uri;
};
+llvm::json::Value toJSON(const ReadResourceParams &);
+bool fromJSON(const llvm::json::Value &, ReadResourceParams &,
+ llvm::json::Path);
-llvm::json::Value toJSON(const ResourceResult &);
-bool fromJSON(const llvm::json::Value &, ResourceResult &, llvm::json::Path);
+/// The server's response to a resources/read request from the client.
+struct ReadResourceResult {
+ std::vector<TextResourceContents> contents;
+};
+llvm::json::Value toJSON(const ReadResourceResult &);
+bool fromJSON(const llvm::json::Value &, ReadResourceResult &,
+ llvm::json::Path);
/// Text provided to or from an LLM.
struct TextContent {
/// The text content of the message.
std::string text;
};
-
llvm::json::Value toJSON(const TextContent &);
bool fromJSON(const llvm::json::Value &, TextContent &, llvm::json::Path);
-struct TextResult {
- std::vector<TextContent> content;
- bool isError = false;
-};
-
-llvm::json::Value toJSON(const TextResult &);
-bool fromJSON(const llvm::json::Value &, TextResult &, llvm::json::Path);
-
+/// Definition for a tool the client can call.
struct ToolDefinition {
/// Unique identifier for the tool.
std::string name;
@@ -198,12 +184,144 @@ struct ToolDefinition {
// JSON Schema for the tool's parameters.
std::optional<llvm::json::Value> inputSchema;
};
-
llvm::json::Value toJSON(const ToolDefinition &);
bool fromJSON(const llvm::json::Value &, ToolDefinition &, llvm::json::Path);
using ToolArguments = std::variant<std::monostate, llvm::json::Value>;
+/// Describes the name and version of an MCP implementation, with an optional
+/// title for UI representation.
+struct Implementation {
+ /// Intended for programmatic or logical use, but used as a display name in
+ /// past specs or fallback (if title isn’t present).
+ std::string name;
+
+ std::string version;
+
+ /// Intended for UI and end-user contexts — optimized to be human-readable and
+ /// easily understood, even by those unfamiliar with domain-specific
+ /// terminology.
+ ///
+ /// If not provided, the name should be used for display (except for Tool,
+ /// where annotations.title should be given precedence over using name, if
+ /// present).
+ std::string title = "";
+};
+llvm::json::Value toJSON(const Implementation &);
+bool fromJSON(const llvm::json::Value &, Implementation &, llvm::json::Path);
+
+/// Capabilities a client may support. Known capabilities are defined here, in
+/// this schema, but this is not a closed set: any client can define its own,
+/// additional capabilities.
+struct ClientCapabilities {};
+llvm::json::Value toJSON(const ClientCapabilities &);
+bool fromJSON(const llvm::json::Value &, ClientCapabilities &,
+ llvm::json::Path);
+
+/// Capabilities that a server may support. Known capabilities are defined here,
+/// in this schema, but this is not a closed set: any server can define its own,
+/// additional capabilities.
+struct ServerCapabilities {
+ bool supportsToolsList = false;
+ bool supportsResourcesList = false;
+ bool supportsResourcesSubscribe = false;
+
+ /// Utilities.
+ bool supportsCompletions = false;
+ bool supportsLogging = false;
+};
+llvm::json::Value toJSON(const ServerCapabilities &);
+bool fromJSON(const llvm::json::Value &, ServerCapabilities &,
+ llvm::json::Path);
+
+/// Initialization
+
+/// This request is sent from the client to the server when it first connects,
+/// asking it to begin initialization.
+struct InitializeParams {
+ /// The latest version of the Model Context Protocol that the client supports.
+ /// The client MAY decide to support older versions as well.
+ std::string protocolVersion;
+
+ ClientCapabilities capabilities;
+
+ Implementation clientInfo;
+};
+llvm::json::Value toJSON(const InitializeParams &);
+bool fromJSON(const llvm::json::Value &, InitializeParams &, llvm::json::Path);
+
+/// After receiving an initialize request from the client, the server sends this
+/// response.
+struct InitializeResult {
+ /// The version of the Model Context Protocol that the server wants to use.
+ /// This may not match the version that the client requested. If the client
+ /// cannot support this version, it MUST disconnect.
+ std::string protocolVersion;
+
+ ServerCapabilities capabilities;
+ Implementation serverInfo;
+
+ /// Instructions describing how to use the server and its features.
+ ///
+ /// This can be used by clients to improve the LLM's understanding of
+ /// available tools, resources, etc. It can be thought of like a "hint" to the
+ /// model. For example, this information MAY be added to the system prompt.
+ std::string instructions = "";
+};
+llvm::json::Value toJSON(const InitializeResult &);
+bool fromJSON(const llvm::json::Value &, InitializeResult &, llvm::json::Path);
+
+/// Special case parameter or result that has no value.
+using Void = std::monostate;
+llvm::json::Value toJSON(const Void &);
+bool fromJSON(const llvm::json::Value &, Void &, llvm::json::Path);
+
+/// The server's response to a `tools/list` request from the client.
+struct ListToolsResult {
+ std::vector<ToolDefinition> tools;
+};
+llvm::json::Value toJSON(const ListToolsResult &);
+bool fromJSON(const llvm::json::Value &, ListToolsResult &, llvm::json::Path);
+
+/// Supported content types, currently only TextContent, but the spec includes
+/// additional content types.
+using ContentBlock = TextContent;
+
+/// Used by the client to invoke a tool provided by the server.
+struct CallToolParams {
+ std::string name;
+ std::optional<llvm::json::Value> arguments;
+};
+llvm::json::Value toJSON(const CallToolParams &);
+bool fromJSON(const llvm::json::Value &, CallToolParams &, llvm::json::Path);
+
+/// The server’s response to a tool call.
+struct CallToolResult {
+ /// A list of content objects that represent the unstructured result of the
+ /// tool call.
+ std::vector<ContentBlock> content;
+
+ /// Whether the tool call ended in an error.
+ ///
+ /// If not set, this is assumed to be false (the call was successful).
+ ///
+ /// Any errors that originate from the tool SHOULD be reported inside the
+ /// result object, with `isError` set to true, not as an MCP protocol-level
+ /// error response. Otherwise, the LLM would not be able to see that an error
+ /// occurred and self-correct.
+ ///
+ /// However, any errors in finding the tool, an error indicating that the
+ /// server does not support tool calls, or any other exceptional conditions,
+ /// should be reported as an MCP error response.
+ bool isError = false;
+
+ /// An optional JSON object that represents the structured result of the tool
+ /// call.
+ std::optional<llvm::json::Value> structuredContent = std::nullopt;
+};
+llvm::json::Value toJSON(const CallToolResult &);
+bool fromJSON(const llvm::json::Value &, CallToolResult &, llvm::json::Path);
+
} // namespace lldb_protocol::mcp
#endif
diff --git a/lldb/include/lldb/Protocol/MCP/Resource.h b/lldb/include/lldb/Protocol/MCP/Resource.h
index 4835d340cd4c..158cffc71ea1 100644
--- a/lldb/include/lldb/Protocol/MCP/Resource.h
+++ b/lldb/include/lldb/Protocol/MCP/Resource.h
@@ -20,7 +20,7 @@ public:
virtual ~ResourceProvider() = default;
virtual std::vector<lldb_protocol::mcp::Resource> GetResources() const = 0;
- virtual llvm::Expected<lldb_protocol::mcp::ResourceResult>
+ virtual llvm::Expected<lldb_protocol::mcp::ReadResourceResult>
ReadResource(llvm::StringRef uri) const = 0;
};
diff --git a/lldb/include/lldb/Protocol/MCP/Server.h b/lldb/include/lldb/Protocol/MCP/Server.h
index 2ac05880de86..b674d5815955 100644
--- a/lldb/include/lldb/Protocol/MCP/Server.h
+++ b/lldb/include/lldb/Protocol/MCP/Server.h
@@ -9,40 +9,55 @@
#ifndef LLDB_PROTOCOL_MCP_SERVER_H
#define LLDB_PROTOCOL_MCP_SERVER_H
+#include "lldb/Host/JSONTransport.h"
+#include "lldb/Host/MainLoop.h"
#include "lldb/Protocol/MCP/Protocol.h"
#include "lldb/Protocol/MCP/Resource.h"
#include "lldb/Protocol/MCP/Tool.h"
+#include "lldb/Protocol/MCP/Transport.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
-#include <mutex>
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/Signals.h"
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
namespace lldb_protocol::mcp {
-class Server {
+class Server : public MCPTransport::MessageHandler {
public:
- Server(std::string name, std::string version);
- virtual ~Server() = default;
+ Server(std::string name, std::string version,
+ std::unique_ptr<MCPTransport> transport_up,
+ lldb_private::MainLoop &loop);
+ ~Server() = default;
+
+ using NotificationHandler = std::function<void(const Notification &)>;
void AddTool(std::unique_ptr<Tool> tool);
void AddResourceProvider(std::unique_ptr<ResourceProvider> resource_provider);
+ void AddNotificationHandler(llvm::StringRef method,
+ NotificationHandler handler);
+
+ llvm::Error Run();
protected:
- virtual Capabilities GetCapabilities() = 0;
+ ServerCapabilities GetCapabilities();
using RequestHandler =
std::function<llvm::Expected<Response>(const Request &)>;
- using NotificationHandler = std::function<void(const Notification &)>;
void AddRequestHandlers();
void AddRequestHandler(llvm::StringRef method, RequestHandler handler);
- void AddNotificationHandler(llvm::StringRef method,
- NotificationHandler handler);
llvm::Expected<std::optional<Message>> HandleData(llvm::StringRef data);
- llvm::Expected<Response> Handle(Request request);
- void Handle(Notification notification);
+ llvm::Expected<Response> Handle(const Request &request);
+ void Handle(const Notification &notification);
llvm::Expected<Response> InitializeHandler(const Request &);
@@ -52,12 +67,21 @@ protected:
llvm::Expected<Response> ResourcesListHandler(const Request &);
llvm::Expected<Response> ResourcesReadHandler(const Request &);
- std::mutex m_mutex;
+ void Received(const Request &) override;
+ void Received(const Response &) override;
+ void Received(const Notification &) override;
+ void OnError(llvm::Error) override;
+ void OnClosed() override;
+
+ void TerminateLoop();
private:
const std::string m_name;
const std::string m_version;
+ std::unique_ptr<MCPTransport> m_transport_up;
+ lldb_private::MainLoop &m_loop;
+
llvm::StringMap<std::unique_ptr<Tool>> m_tools;
std::vector<std::unique_ptr<ResourceProvider>> m_resource_providers;
@@ -65,6 +89,42 @@ private:
llvm::StringMap<NotificationHandler> m_notification_handlers;
};
+class ServerInfoHandle;
+
+/// Information about this instance of lldb's MCP server for lldb-mcp to use to
+/// coordinate connecting an lldb-mcp client.
+struct ServerInfo {
+ std::string connection_uri;
+
+ /// Writes the server info into a unique file in `~/.lldb`.
+ static llvm::Expected<ServerInfoHandle> Write(const ServerInfo &);
+ /// Loads any server info saved in `~/.lldb`.
+ static llvm::Expected<std::vector<ServerInfo>> Load();
+};
+llvm::json::Value toJSON(const ServerInfo &);
+bool fromJSON(const llvm::json::Value &, ServerInfo &, llvm::json::Path);
+
+/// A handle that tracks the server info on disk and cleans up the disk record
+/// once it is no longer referenced.
+class ServerInfoHandle {
+public:
+ ServerInfoHandle();
+ explicit ServerInfoHandle(llvm::StringRef filename);
+ ~ServerInfoHandle();
+
+ ServerInfoHandle(ServerInfoHandle &&other);
+ ServerInfoHandle &operator=(ServerInfoHandle &&other) noexcept;
+
+ /// ServerIinfoHandle is not copyable.
+ /// @{
+ ServerInfoHandle(const ServerInfoHandle &) = delete;
+ ServerInfoHandle &operator=(const ServerInfoHandle &) = delete;
+ /// @}
+
+private:
+ llvm::SmallString<128> m_filename;
+};
+
} // namespace lldb_protocol::mcp
#endif
diff --git a/lldb/include/lldb/Protocol/MCP/Tool.h b/lldb/include/lldb/Protocol/MCP/Tool.h
index 96669d135716..6c9f05161f8e 100644
--- a/lldb/include/lldb/Protocol/MCP/Tool.h
+++ b/lldb/include/lldb/Protocol/MCP/Tool.h
@@ -10,6 +10,7 @@
#define LLDB_PROTOCOL_MCP_TOOL_H
#include "lldb/Protocol/MCP/Protocol.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/JSON.h"
#include <string>
@@ -20,7 +21,7 @@ public:
Tool(std::string name, std::string description);
virtual ~Tool() = default;
- virtual llvm::Expected<lldb_protocol::mcp::TextResult>
+ virtual llvm::Expected<lldb_protocol::mcp::CallToolResult>
Call(const lldb_protocol::mcp::ToolArguments &args) = 0;
virtual std::optional<llvm::json::Value> GetSchema() const {
diff --git a/lldb/include/lldb/Protocol/MCP/Transport.h b/lldb/include/lldb/Protocol/MCP/Transport.h
new file mode 100644
index 000000000000..47c2ccfc44df
--- /dev/null
+++ b/lldb/include/lldb/Protocol/MCP/Transport.h
@@ -0,0 +1,48 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_PROTOCOL_MCP_TRANSPORT_H
+#define LLDB_PROTOCOL_MCP_TRANSPORT_H
+
+#include "lldb/Host/JSONTransport.h"
+#include "lldb/Protocol/MCP/Protocol.h"
+#include "lldb/lldb-forward.h"
+#include "llvm/ADT/FunctionExtras.h"
+#include "llvm/ADT/StringRef.h"
+
+namespace lldb_protocol::mcp {
+
+/// Generic transport that uses the MCP protocol.
+using MCPTransport = lldb_private::Transport<Request, Response, Notification>;
+
+/// Generic logging callback, to allow the MCP server / client / transport layer
+/// to be independent of the lldb log implementation.
+using LogCallback = llvm::unique_function<void(llvm::StringRef message)>;
+
+class Transport final
+ : public lldb_private::JSONRPCTransport<Request, Response, Notification> {
+public:
+ Transport(lldb::IOObjectSP in, lldb::IOObjectSP out,
+ LogCallback log_callback = {});
+ virtual ~Transport() = default;
+
+ /// Transport is not copyable.
+ /// @{
+ Transport(const Transport &) = delete;
+ void operator=(const Transport &) = delete;
+ /// @}
+
+ void Log(llvm::StringRef message) override;
+
+private:
+ LogCallback m_log_callback;
+};
+
+} // namespace lldb_protocol::mcp
+
+#endif
diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h
index bbc615d9fdc3..ff67e002e5b0 100644
--- a/lldb/include/lldb/Symbol/SymbolFile.h
+++ b/lldb/include/lldb/Symbol/SymbolFile.h
@@ -332,12 +332,12 @@ public:
/// Resolves the function corresponding to the specified LLDB function
/// call \c label.
///
- /// \param[in] label The FunctionCallLabel to be resolved.
+ /// \param[in,out] label The FunctionCallLabel to be resolved.
///
/// \returns An llvm::Error if the specified \c label couldn't be resolved.
/// Returns the resolved function (as a SymbolContext) otherwise.
virtual llvm::Expected<SymbolContext>
- ResolveFunctionCallLabel(const FunctionCallLabel &label) {
+ ResolveFunctionCallLabel(FunctionCallLabel &label) {
return llvm::createStringError("Not implemented");
}
@@ -488,13 +488,16 @@ public:
return false;
};
- /// Get number of loaded/parsed DWO files. This is emitted in "statistics
- /// dump"
+ /// Retrieves statistics about DWO files associated with this symbol file.
+ /// This function returns a DWOStats struct containing:
+ /// - The number of successfully loaded/parsed DWO files.
+ /// - The total number of DWO files encountered.
+ /// - The number of DWO CUs that failed to load due to errors.
+ /// If this symbol file does not support DWO files, all counts will be zero.
///
/// \returns
- /// A pair containing (loaded_dwo_count, total_dwo_count). If this
- /// symbol file doesn't support DWO files, both counts will be 0.
- virtual std::pair<uint32_t, uint32_t> GetDwoFileCounts() { return {0, 0}; }
+ /// A DWOStats struct with loaded, total, and error counts for DWO files.
+ virtual DWOStats GetDwoStats() { return {}; }
virtual lldb::TypeSP
MakeType(lldb::user_id_t uid, ConstString name,
diff --git a/lldb/include/lldb/Target/CoreFileMemoryRanges.h b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
index 78d01acca324..ef56a02ddee2 100644
--- a/lldb/include/lldb/Target/CoreFileMemoryRanges.h
+++ b/lldb/include/lldb/Target/CoreFileMemoryRanges.h
@@ -50,7 +50,7 @@ class CoreFileMemoryRanges
CoreFileMemoryRange> {
public:
/// Finalize and merge all overlapping ranges in this collection. Ranges
- /// will be seperated based on permissions.
+ /// will be separated based on permissions.
Status FinalizeCoreFileSaveRanges();
};
} // namespace lldb_private
diff --git a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
index 534516085091..dafa41c11327 100644
--- a/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
+++ b/lldb/include/lldb/Target/InstrumentationRuntimeStopInfo.h
@@ -24,6 +24,9 @@ public:
return lldb::eStopReasonInstrumentation;
}
+ std::optional<uint32_t>
+ GetSuggestedStackFrameIndex(bool inlined_stack) override;
+
const char *GetDescription() override;
bool DoShouldNotify(Event *event_ptr) override { return true; }
diff --git a/lldb/include/lldb/Target/RegisterContextUnwind.h b/lldb/include/lldb/Target/RegisterContextUnwind.h
index b10a364823b8..52c28fd76da9 100644
--- a/lldb/include/lldb/Target/RegisterContextUnwind.h
+++ b/lldb/include/lldb/Target/RegisterContextUnwind.h
@@ -21,6 +21,7 @@
namespace lldb_private {
class UnwindLLDB;
+class ArchitectureArm;
class RegisterContextUnwind : public lldb_private::RegisterContext {
public:
@@ -72,6 +73,25 @@ public:
// above asynchronous trap handlers (sigtramp) for instance.
bool BehavesLikeZerothFrame() const override;
+protected:
+ // Provide a location for where THIS function saved the CALLER's register
+ // value, or a frame "below" this one saved it. That is, this function doesn't
+ // modify the register, it may call a function that does & saved it to stack.
+ //
+ // The ConcreteRegisterLocation type may be set to eRegisterNotAvailable --
+ // this will happen for a volatile register being queried mid-stack. Instead
+ // of floating frame 0's contents of that register up the stack (which may or
+ // may not be the value of that reg when the function was executing), we won't
+ // return any value.
+ //
+ // If a non-volatile register (a "preserved" register, a callee-preserved
+ // register) is requested mid-stack, and no frames "below" the requested stack
+ // have saved the register anywhere, it is safe to assume that frame 0's
+ // register value is the same.
+ lldb_private::UnwindLLDB::RegisterSearchResult SavedLocationForRegister(
+ uint32_t lldb_regnum,
+ lldb_private::UnwindLLDB::ConcreteRegisterLocation &regloc);
+
private:
enum FrameType {
eNormalFrame,
@@ -86,6 +106,8 @@ private:
// UnwindLLDB needs to pass around references to ConcreteRegisterLocations
friend class UnwindLLDB;
+ // Architecture may need to retrieve caller register values from this frame
+ friend class ArchitectureArm;
// Returns true if we have an unwind loop -- the same stack frame unwinding
// multiple times.
@@ -130,27 +152,6 @@ private:
void PropagateTrapHandlerFlagFromUnwindPlan(
std::shared_ptr<const UnwindPlan> unwind_plan);
- // Provide a location for where THIS function saved the CALLER's register
- // value
- // Or a frame "below" this one saved it, i.e. a function called by this one,
- // preserved a register that this
- // function didn't modify/use.
- //
- // The ConcreteRegisterLocation type may be set to eRegisterNotAvailable --
- // this will happen for a volatile register being queried mid-stack. Instead
- // of floating frame 0's contents of that register up the stack (which may or
- // may not be the value of that reg when the function was executing), we won't
- // return any value.
- //
- // If a non-volatile register (a "preserved" register) is requested mid-stack
- // and no frames "below" the requested
- // stack have saved the register anywhere, it is safe to assume that frame 0's
- // register values are still the same
- // as the requesting frame's.
- lldb_private::UnwindLLDB::RegisterSearchResult SavedLocationForRegister(
- uint32_t lldb_regnum,
- lldb_private::UnwindLLDB::ConcreteRegisterLocation &regloc);
-
std::optional<UnwindPlan::Row::AbstractRegisterLocation>
GetAbstractRegisterLocation(uint32_t lldb_regnum, lldb::RegisterKind &kind);
@@ -202,6 +203,8 @@ private:
std::shared_ptr<const UnwindPlan> GetFullUnwindPlanForFrame();
+ lldb::UnwindPlanSP TryAdoptArchitectureUnwindPlan();
+
void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3)));
void UnwindLogMsgVerbose(const char *fmt, ...)
diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h
index d4104bfe49d2..cdbe8ae3c677 100644
--- a/lldb/include/lldb/Target/StackFrame.h
+++ b/lldb/include/lldb/Target/StackFrame.h
@@ -60,10 +60,9 @@ public:
/// local variables.
History,
- /// An artificial stack frame (e.g. a synthesized result of inferring
- /// missing tail call frames from a backtrace) with limited support for
- /// local variables.
- Artificial
+ /// An synthetic stack frame (e.g. a synthesized result from script
+ /// resource) possibly without support for local variables or register.
+ Synthetic
};
/// Construct a StackFrame object without supplying a RegisterContextSP.
@@ -109,7 +108,8 @@ public:
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
lldb::user_id_t concrete_frame_idx, lldb::addr_t cfa,
bool cfa_is_valid, lldb::addr_t pc, Kind frame_kind,
- bool behaves_like_zeroth_frame, const SymbolContext *sc_ptr);
+ bool artificial, bool behaves_like_zeroth_frame,
+ const SymbolContext *sc_ptr);
StackFrame(const lldb::ThreadSP &thread_sp, lldb::user_id_t frame_idx,
lldb::user_id_t concrete_frame_idx,
@@ -398,7 +398,10 @@ public:
///
/// \return
/// true if this is an inlined frame.
- bool IsInlined();
+ virtual bool IsInlined();
+
+ /// Query whether this frame is synthetic.
+ bool IsSynthetic() const;
/// Query whether this frame is part of a historical backtrace.
bool IsHistorical() const;
@@ -406,12 +409,12 @@ public:
/// Query whether this frame is artificial (e.g a synthesized result of
/// inferring missing tail call frames from a backtrace). Artificial frames
/// may have limited support for inspecting variables.
- bool IsArtificial() const;
+ virtual bool IsArtificial() const;
/// Query whether this frame should be hidden from backtraces. Frame
/// recognizers can customize this behavior and hide distracting
/// system implementation details this way.
- bool IsHidden();
+ virtual bool IsHidden();
/// Language plugins can use this API to report language-specific
/// runtime information about this compile unit, such as additional
@@ -422,13 +425,13 @@ public:
///
/// /// \return
/// A C-String containing the function demangled name. Can be null.
- const char *GetFunctionName();
+ virtual const char *GetFunctionName();
/// Get the frame's demangled display name.
///
/// /// \return
/// A C-String containing the function demangled display name. Can be null.
- const char *GetDisplayFunctionName();
+ virtual const char *GetDisplayFunctionName();
/// Query this frame to find what frame it is in this Thread's
/// StackFrameList.
@@ -540,18 +543,7 @@ protected:
bool HasCachedData() const;
-private:
- /// Private methods, called from GetValueForVariableExpressionPath.
- /// See that method for documentation of parameters and return value.
- lldb::ValueObjectSP LegacyGetValueForVariableExpressionPath(
- llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
- uint32_t options, lldb::VariableSP &var_sp, Status &error);
-
- lldb::ValueObjectSP DILGetValueForVariableExpressionPath(
- llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
- uint32_t options, lldb::VariableSP &var_sp, Status &error);
-
- /// For StackFrame only.
+ /// For StackFrame and derived classes only.
/// \{
lldb::ThreadWP m_thread_wp;
uint32_t m_frame_index;
@@ -571,6 +563,10 @@ private:
/// Does this frame have a CFA? Different from CFA == LLDB_INVALID_ADDRESS.
bool m_cfa_is_valid;
Kind m_stack_frame_kind;
+ /// Is this an artificial stack frame (e.g. a synthesized result of inferring
+ /// missing tail call frames from a backtrace) with limited support for
+ /// local variables. Orthogonal to `StackFrame::Kind`.
+ bool m_artificial;
/// Whether this frame behaves like the zeroth frame, in the sense
/// that its pc value might not immediately follow a call (and thus might
@@ -584,6 +580,17 @@ private:
StreamString m_disassembly;
std::recursive_mutex m_mutex;
+private:
+ /// Private methods, called from GetValueForVariableExpressionPath.
+ /// See that method for documentation of parameters and return value.
+ lldb::ValueObjectSP LegacyGetValueForVariableExpressionPath(
+ llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
+ uint32_t options, lldb::VariableSP &var_sp, Status &error);
+
+ lldb::ValueObjectSP DILGetValueForVariableExpressionPath(
+ llvm::StringRef var_expr, lldb::DynamicValueType use_dynamic,
+ uint32_t options, lldb::VariableSP &var_sp, Status &error);
+
StackFrame(const StackFrame &) = delete;
const StackFrame &operator=(const StackFrame &) = delete;
};
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index e5a6e942d743..ea9aab86b8ea 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -46,6 +46,9 @@ public:
/// Mark a stack frame as the currently selected frame and return its index.
uint32_t SetSelectedFrame(lldb_private::StackFrame *frame);
+ /// Resets the selected frame index of this object.
+ void ClearSelectedFrameIndex();
+
/// Get the currently selected frame index.
/// We should only call SelectMostRelevantFrame if (a) the user hasn't already
/// selected a frame, and (b) if this really is a user facing
@@ -172,6 +175,15 @@ protected:
/// The currently selected frame. An optional is used to record whether anyone
/// has set the selected frame on this stack yet. We only let recognizers
/// change the frame if this is the first time GetSelectedFrame is called.
+ ///
+ /// Thread-safety:
+ /// This member is not protected by a mutex.
+ /// LLDB really only should have an opinion about the selected frame index
+ /// when a process stops, before control gets handed back to the user.
+ /// After that, it's up to them to change it whenever they feel like it.
+ /// If two parts of lldb decided they wanted to be in control of the selected
+ /// frame index on stop the right way to fix it would need to be some explicit
+ /// negotiation for who gets to control this.
std::optional<uint32_t> m_selected_frame_idx;
/// Protect access to m_selected_frame_idx. Always acquire after m_list_mutex
diff --git a/lldb/include/lldb/Target/StackID.h b/lldb/include/lldb/Target/StackID.h
index fddbc8e48dfd..c2a5d733dcd6 100644
--- a/lldb/include/lldb/Target/StackID.h
+++ b/lldb/include/lldb/Target/StackID.h
@@ -10,7 +10,6 @@
#define LLDB_TARGET_STACKID_H
#include "lldb/Core/AddressRange.h"
-#include "lldb/lldb-private.h"
namespace lldb_private {
@@ -18,15 +17,11 @@ class Process;
class StackID {
public:
- // Constructors and Destructors
StackID() = default;
explicit StackID(lldb::addr_t pc, lldb::addr_t cfa,
SymbolContextScope *symbol_scope, Process *process);
- StackID(const StackID &rhs)
- : m_pc(rhs.m_pc), m_cfa(rhs.m_cfa), m_symbol_scope(rhs.m_symbol_scope) {}
-
~StackID() = default;
lldb::addr_t GetPC() const { return m_pc; }
@@ -51,41 +46,28 @@ public:
void Dump(Stream *s);
- // Operators
- const StackID &operator=(const StackID &rhs) {
- if (this != &rhs) {
- m_pc = rhs.m_pc;
- m_cfa = rhs.m_cfa;
- m_symbol_scope = rhs.m_symbol_scope;
- }
- return *this;
- }
-
protected:
friend class StackFrame;
void SetPC(lldb::addr_t pc, Process *process);
void SetCFA(lldb::addr_t cfa, Process *process);
- lldb::addr_t m_pc =
- LLDB_INVALID_ADDRESS; // The pc value for the function/symbol for this
- // frame. This will
- // only get used if the symbol scope is nullptr (the code where we are
- // stopped is not represented by any function or symbol in any shared
- // library).
- lldb::addr_t m_cfa =
- LLDB_INVALID_ADDRESS; // The call frame address (stack pointer) value
- // at the beginning of the function that uniquely
- // identifies this frame (along with m_symbol_scope
- // below)
- SymbolContextScope *m_symbol_scope =
- nullptr; // If nullptr, there is no block or symbol for this frame.
- // If not nullptr, this will either be the scope for the
- // lexical block for the frame, or the scope for the
- // symbol. Symbol context scopes are always be unique
- // pointers since the are part of the Block and Symbol
- // objects and can easily be used to tell if a stack ID
- // is the same as another.
+ /// The pc value for the function/symbol for this frame. This will only get
+ /// used if the symbol scope is nullptr (the code where we are stopped is not
+ /// represented by any function or symbol in any shared library).
+ lldb::addr_t m_pc = LLDB_INVALID_ADDRESS;
+
+ /// The call frame address (stack pointer) value at the beginning of the
+ /// function that uniquely identifies this frame (along with m_symbol_scope
+ /// below)
+ lldb::addr_t m_cfa = LLDB_INVALID_ADDRESS;
+
+ /// If nullptr, there is no block or symbol for this frame. If not nullptr,
+ /// this will either be the scope for the lexical block for the frame, or the
+ /// scope for the symbol. Symbol context scopes are always be unique pointers
+ /// since the are part of the Block and Symbol objects and can easily be used
+ /// to tell if a stack ID is the same as another.
+ SymbolContextScope *m_symbol_scope = nullptr;
};
bool operator==(const StackID &lhs, const StackID &rhs);
diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h
index 55dff8861a9a..d6983bb0b9d2 100644
--- a/lldb/include/lldb/Target/Statistics.h
+++ b/lldb/include/lldb/Target/Statistics.h
@@ -123,6 +123,25 @@ struct StatsSuccessFail {
uint32_t failures = 0;
};
+/// Holds statistics about DWO (Debug With Object) files.
+struct DWOStats {
+ uint32_t loaded_dwo_file_count = 0;
+ uint32_t dwo_file_count = 0;
+ uint32_t dwo_error_count = 0;
+
+ DWOStats &operator+=(const DWOStats &rhs) {
+ loaded_dwo_file_count += rhs.loaded_dwo_file_count;
+ dwo_file_count += rhs.dwo_file_count;
+ dwo_error_count += rhs.dwo_error_count;
+ return *this;
+ }
+
+ friend DWOStats operator+(DWOStats lhs, const DWOStats &rhs) {
+ lhs += rhs;
+ return lhs;
+ }
+};
+
/// A class that represents statistics for a since lldb_private::Module.
struct ModuleStats {
llvm::json::Value ToJSON() const;
@@ -153,8 +172,7 @@ struct ModuleStats {
bool symtab_stripped = false;
bool debug_info_had_variable_errors = false;
bool debug_info_had_incomplete_types = false;
- uint32_t dwo_file_count = 0;
- uint32_t loaded_dwo_file_count = 0;
+ DWOStats dwo_stats;
};
struct ConstStringStats {
diff --git a/lldb/include/lldb/Target/StopInfo.h b/lldb/include/lldb/Target/StopInfo.h
index 368ec51d8189..cdd6a6fbe6aa 100644
--- a/lldb/include/lldb/Target/StopInfo.h
+++ b/lldb/include/lldb/Target/StopInfo.h
@@ -97,6 +97,12 @@ public:
/// and silently continue again one more time.
virtual bool WasContinueInterrupted(Thread &thread) { return false; }
+ virtual uint32_t GetStopReasonDataCount() const { return 0; }
+ virtual uint64_t GetStopReasonDataAtIndex(uint32_t idx) {
+ // Handle all the common cases that have no data.
+ return 0;
+ }
+
// Sometimes the thread plan logic will know that it wants a given stop to
// stop or not, regardless of what the ordinary logic for that StopInfo would
// dictate. The main example of this is the ThreadPlanCallFunction, which
diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h
index 6ede7fa301a8..688c056da263 100644
--- a/lldb/include/lldb/Target/Thread.h
+++ b/lldb/include/lldb/Target/Thread.h
@@ -479,6 +479,11 @@ public:
bool SetSelectedFrameByIndexNoisily(uint32_t frame_idx,
Stream &output_stream);
+ /// Resets the selected frame index of this object.
+ void ClearSelectedFrameIndex() {
+ return GetStackFrameList()->ClearSelectedFrameIndex();
+ }
+
void SetDefaultFileAndLineToSelectedFrame() {
GetStackFrameList()->SetDefaultFileAndLineToSelectedFrame();
}
diff --git a/lldb/include/lldb/Target/UnwindLLDB.h b/lldb/include/lldb/Target/UnwindLLDB.h
index 88180b37fd93..29b3ab9c9029 100644
--- a/lldb/include/lldb/Target/UnwindLLDB.h
+++ b/lldb/include/lldb/Target/UnwindLLDB.h
@@ -22,6 +22,7 @@
namespace lldb_private {
class RegisterContextUnwind;
+class ArchitectureArm;
class UnwindLLDB : public lldb_private::Unwind {
public:
@@ -37,6 +38,7 @@ public:
protected:
friend class lldb_private::RegisterContextUnwind;
+ friend class lldb_private::ArchitectureArm;
/// An UnwindPlan::Row::AbstractRegisterLocation, combined with the register
/// context and memory for a specific stop point, is used to create a
diff --git a/lldb/include/lldb/Utility/AnsiTerminal.h b/lldb/include/lldb/Utility/AnsiTerminal.h
index 5c99341ad888..7db184ad6722 100644
--- a/lldb/include/lldb/Utility/AnsiTerminal.h
+++ b/lldb/include/lldb/Utility/AnsiTerminal.h
@@ -260,6 +260,11 @@ inline std::string TrimAndPad(llvm::StringRef str, size_t visible_length,
return result;
}
+inline size_t ColumnWidth(llvm::StringRef str) {
+ std::string stripped = ansi::StripAnsiTerminalCodes(str);
+ return llvm::sys::locale::columnWidth(stripped);
+}
+
} // namespace ansi
} // namespace lldb_private
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
index 709f0639135f..1d10755c46e3 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -21,7 +21,9 @@ enum class NodeKind {
eArraySubscriptNode,
eBitExtractionNode,
eErrorNode,
+ eFloatLiteralNode,
eIdentifierNode,
+ eIntegerLiteralNode,
eMemberOfNode,
eUnaryOpNode,
};
@@ -178,6 +180,52 @@ private:
int64_t m_last_index;
};
+enum class IntegerTypeSuffix { None, Long, LongLong };
+
+class IntegerLiteralNode : public ASTNode {
+public:
+ IntegerLiteralNode(uint32_t location, llvm::APInt value, uint32_t radix,
+ bool is_unsigned, IntegerTypeSuffix type)
+ : ASTNode(location, NodeKind::eIntegerLiteralNode),
+ m_value(std::move(value)), m_radix(radix), m_is_unsigned(is_unsigned),
+ m_type(type) {}
+
+ llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+ const llvm::APInt &GetValue() const { return m_value; }
+ uint32_t GetRadix() const { return m_radix; }
+ bool IsUnsigned() const { return m_is_unsigned; }
+ IntegerTypeSuffix GetTypeSuffix() const { return m_type; }
+
+ static bool classof(const ASTNode *node) {
+ return node->GetKind() == NodeKind::eIntegerLiteralNode;
+ }
+
+private:
+ llvm::APInt m_value;
+ uint32_t m_radix;
+ bool m_is_unsigned;
+ IntegerTypeSuffix m_type;
+};
+
+class FloatLiteralNode : public ASTNode {
+public:
+ FloatLiteralNode(uint32_t location, llvm::APFloat value)
+ : ASTNode(location, NodeKind::eFloatLiteralNode),
+ m_value(std::move(value)) {}
+
+ llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+ const llvm::APFloat &GetValue() const { return m_value; }
+
+ static bool classof(const ASTNode *node) {
+ return node->GetKind() == NodeKind::eFloatLiteralNode;
+ }
+
+private:
+ llvm::APFloat m_value;
+};
+
/// This class contains one Visit method for each specialized type of
/// DIL AST node. The Visit methods are used to dispatch a DIL AST node to
/// the correct function in the DIL expression evaluator for evaluating that
@@ -195,6 +243,10 @@ public:
Visit(const ArraySubscriptNode *node) = 0;
virtual llvm::Expected<lldb::ValueObjectSP>
Visit(const BitFieldExtractionNode *node) = 0;
+ virtual llvm::Expected<lldb::ValueObjectSP>
+ Visit(const IntegerLiteralNode *node) = 0;
+ virtual llvm::Expected<lldb::ValueObjectSP>
+ Visit(const FloatLiteralNode *node) = 0;
};
} // namespace lldb_private::dil
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index 45e29b3ddcd7..5a48c2c989f4 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -54,6 +54,15 @@ private:
Visit(const ArraySubscriptNode *node) override;
llvm::Expected<lldb::ValueObjectSP>
Visit(const BitFieldExtractionNode *node) override;
+ llvm::Expected<lldb::ValueObjectSP>
+ Visit(const IntegerLiteralNode *node) override;
+ llvm::Expected<lldb::ValueObjectSP>
+ Visit(const FloatLiteralNode *node) override;
+
+ llvm::Expected<CompilerType>
+ PickIntegerType(lldb::TypeSystemSP type_system,
+ std::shared_ptr<ExecutionContextScope> ctx,
+ const IntegerLiteralNode *literal);
// Used by the interpreter to create objects, perform casts, etc.
lldb::TargetSP m_target;
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 9c1ba9768025..4345e6ce7f26 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -28,12 +28,14 @@ public:
arrow,
coloncolon,
eof,
+ float_constant,
identifier,
+ integer_constant,
l_paren,
l_square,
minus,
- numeric_constant,
period,
+ plus,
r_paren,
r_square,
star,
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index 9eda7bac4a36..90df109337dc 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -96,6 +96,9 @@ private:
std::string ParseIdExpression();
std::string ParseUnqualifiedId();
std::optional<int64_t> ParseIntegerConstant();
+ ASTNodeUP ParseNumericLiteral();
+ ASTNodeUP ParseIntegerLiteral();
+ ASTNodeUP ParseFloatingPointLiteral();
void BailOut(const std::string &error, uint32_t loc, uint16_t err_len);
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 483dce98ea42..af5656b3dcad 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -187,6 +187,7 @@ class SaveCoreOptions;
class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
+class ScriptedFrameInterface;
class ScriptedMetadata;
class ScriptedBreakpointInterface;
class ScriptedPlatformInterface;
@@ -408,6 +409,8 @@ typedef std::shared_ptr<lldb_private::RecognizedStackFrame>
typedef std::shared_ptr<lldb_private::ScriptSummaryFormat>
ScriptSummaryFormatSP;
typedef std::shared_ptr<lldb_private::ScriptInterpreter> ScriptInterpreterSP;
+typedef std::shared_ptr<lldb_private::ScriptedFrameInterface>
+ ScriptedFrameInterfaceSP;
typedef std::shared_ptr<lldb_private::ScriptedMetadata> ScriptedMetadataSP;
typedef std::unique_ptr<lldb_private::ScriptedPlatformInterface>
ScriptedPlatformInterfaceUP;