aboutsummaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/bindings/python/python-wrapper.swig84
-rw-r--r--lldb/cmake/modules/LLDBConfig.cmake26
-rw-r--r--lldb/docs/index.rst1
-rw-r--r--lldb/docs/resources/build.rst5
-rw-r--r--lldb/docs/resources/lldbgdbremote.md16
-rw-r--r--lldb/include/lldb/API/SBSymbolContext.h2
-rw-r--r--lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h4
-rw-r--r--lldb/include/lldb/Core/ModuleList.h6
-rw-r--r--lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h32
-rw-r--r--lldb/include/lldb/Interpreter/ScriptInterpreter.h30
-rw-r--r--lldb/include/lldb/Target/Process.h2
-rw-r--r--lldb/include/lldb/Target/StackFrameList.h5
-rw-r--r--lldb/include/lldb/lldb-forward.h3
-rw-r--r--lldb/packages/Python/lldbsuite/test/dotest.py8
-rw-r--r--lldb/packages/Python/lldbsuite/test/lldbgdbclient.py4
-rw-r--r--lldb/packages/Python/lldbsuite/test/lldbtest.py3
-rw-r--r--lldb/source/API/CMakeLists.txt6
-rw-r--r--lldb/source/API/SBType.cpp59
-rw-r--r--lldb/source/API/SBTypeFilter.cpp2
-rw-r--r--lldb/source/API/SBTypeNameSpecifier.cpp4
-rw-r--r--lldb/source/API/SBTypeSynthetic.cpp8
-rw-r--r--lldb/source/API/SBValue.cpp10
-rw-r--r--lldb/source/Breakpoint/Breakpoint.cpp3
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverName.cpp8
-rw-r--r--lldb/source/Breakpoint/BreakpointResolverScripted.cpp52
-rw-r--r--lldb/source/Commands/CommandCompletions.cpp2
-rw-r--r--lldb/source/Commands/CommandObjectCommands.cpp13
-rw-r--r--lldb/source/Commands/CommandObjectFrame.cpp5
-rw-r--r--lldb/source/Core/IOHandlerCursesGUI.cpp96
-rw-r--r--lldb/source/Core/ModuleList.cpp6
-rw-r--r--lldb/source/DataFormatters/FormatManager.cpp5
-rw-r--r--lldb/source/DataFormatters/TypeCategoryMap.cpp2
-rw-r--r--lldb/source/DataFormatters/ValueObjectPrinter.cpp8
-rw-r--r--lldb/source/Host/common/FileSystem.cpp6
-rw-r--r--lldb/source/Host/windows/MainLoopWindows.cpp5
-rw-r--r--lldb/source/Host/windows/PipeWindows.cpp6
-rw-r--r--lldb/source/Interpreter/CommandInterpreter.cpp3
-rw-r--r--lldb/source/Interpreter/ScriptInterpreter.cpp7
-rw-r--r--lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h6
-rw-r--r--lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp4
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt2
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp140
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp63
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h26
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp174
-rw-r--r--lldb/source/Plugins/Language/CPlusPlus/MsvcStlTree.cpp407
-rw-r--r--lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp2
-rw-r--r--lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp6
-rw-r--r--lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp4
-rw-r--r--lldb/source/Plugins/Process/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp3
-rw-r--r--lldb/source/Plugins/Process/Linux/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp49
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h23
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp67
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.cpp77
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.h31
-rw-r--r--lldb/source/Plugins/Process/Utility/AuxVector.cpp3
-rw-r--r--lldb/source/Plugins/Process/Utility/AuxVector.h5
-rw-r--r--lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h2
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp53
-rw-r--r--lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h25
-rw-r--r--lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp13
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp20
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h2
-rw-r--r--lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp2
-rw-r--r--lldb/source/Plugins/Process/wasm/CMakeLists.txt10
-rw-r--r--lldb/source/Plugins/Process/wasm/ProcessWasm.cpp133
-rw-r--r--lldb/source/Plugins/Process/wasm/ProcessWasm.h91
-rw-r--r--lldb/source/Plugins/Process/wasm/ThreadWasm.cpp34
-rw-r--r--lldb/source/Plugins/Process/wasm/ThreadWasm.h38
-rw-r--r--lldb/source/Plugins/Process/wasm/UnwindWasm.cpp85
-rw-r--r--lldb/source/Plugins/Process/wasm/UnwindWasm.h51
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt1
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp2
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h1
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp100
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h53
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp15
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h13
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h10
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp78
-rw-r--r--lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h14
-rw-r--r--lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp6
-rw-r--r--lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp5
-rw-r--r--lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp2
-rw-r--r--lldb/source/Symbol/Type.cpp3
-rw-r--r--lldb/source/Target/InstrumentationRuntime.cpp10
-rw-r--r--lldb/source/Target/Platform.cpp7
-rw-r--r--lldb/source/Target/StackFrameList.cpp6
-rw-r--r--lldb/source/Target/StackFrameRecognizer.cpp2
-rw-r--r--lldb/source/Target/Target.cpp5
-rw-r--r--lldb/source/Target/ThreadPlanStepRange.cpp4
-rw-r--r--lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py32
-rw-r--r--lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py4
-rw-r--r--lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py24
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py32
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py11
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/main.cpp2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py18
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py32
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py33
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp2
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py8
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp1
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/Makefile4
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py44
-rw-r--r--lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/main.cpp12
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py11
-rw-r--r--lldb/test/API/functionalities/gdb_remote_client/TestWasm.py28
-rw-r--r--lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py11
-rw-r--r--lldb/test/API/linux/aarch64/mte_core_file/core.mtebin20608 -> 417920 bytes
-rw-r--r--lldb/test/API/linux/aarch64/mte_core_file/core.nomtebin20480 -> 32768 bytes
-rw-r--r--lldb/test/API/linux/aarch64/mte_core_file/main.c2
-rw-r--r--lldb/test/CMakeLists.txt7
-rw-r--r--lldb/test/Shell/RPC/Generator/Inputs/SBDummy.h0
-rw-r--r--lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test9
-rw-r--r--lldb/test/Shell/RPC/Generator/lit.local.cfg3
-rw-r--r--lldb/test/Shell/helper/toolchain.py10
-rw-r--r--lldb/test/Shell/lit.site.cfg.py.in1
-rw-r--r--lldb/tools/CMakeLists.txt6
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.cpp6
-rw-r--r--lldb/tools/lldb-rpc-gen/CMakeLists.txt23
-rw-r--r--lldb/tools/lldb-rpc-gen/RPCCommon.cpp493
-rw-r--r--lldb/tools/lldb-rpc-gen/RPCCommon.h107
-rw-r--r--lldb/tools/lldb-rpc-gen/lldb-rpc-gen.cpp (renamed from lldb/tools/lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp)38
-rw-r--r--lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp (renamed from lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp)0
-rw-r--r--lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.h (renamed from lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.h)0
-rw-r--r--lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp (renamed from lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp)0
-rw-r--r--lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.h (renamed from lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.h)0
-rw-r--r--lldb/tools/lldb-rpc/CMakeLists.txt22
-rw-r--r--lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake80
-rw-r--r--lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake101
-rw-r--r--lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp19
134 files changed, 3164 insertions, 609 deletions
diff --git a/lldb/bindings/python/python-wrapper.swig b/lldb/bindings/python/python-wrapper.swig
index 3d1d04e..2c30d53 100644
--- a/lldb/bindings/python/python-wrapper.swig
+++ b/lldb/bindings/python/python-wrapper.swig
@@ -229,78 +229,6 @@ PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject
return pfunc(SWIGBridge::ToSWIGWrapper(std::move(debugger_sp)), dict);
}
-PythonObject lldb_private::python::SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
- const char *python_class_name, const char *session_dictionary_name,
- const StructuredDataImpl &args_impl,
- const lldb::BreakpointSP &breakpoint_sp) {
-
- if (python_class_name == NULL || python_class_name[0] == '\0' ||
- !session_dictionary_name)
- return PythonObject();
-
- PyErr_Cleaner py_err_cleaner(true);
-
- auto dict = PythonModule::MainModule().ResolveName<PythonDictionary>(
- session_dictionary_name);
- auto pfunc = PythonObject::ResolveNameWithDictionary<PythonCallable>(
- python_class_name, dict);
-
- if (!pfunc.IsAllocated())
- return PythonObject();
-
- PythonObject result =
- pfunc(SWIGBridge::ToSWIGWrapper(breakpoint_sp), SWIGBridge::ToSWIGWrapper(args_impl), dict);
- // FIXME: At this point we should check that the class we found supports all
- // the methods that we need.
-
- if (result.IsAllocated()) {
- // Check that __callback__ is defined:
- auto callback_func = result.ResolveName<PythonCallable>("__callback__");
- if (callback_func.IsAllocated())
- return result;
- }
- return PythonObject();
-}
-
-unsigned int lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
- void *implementor, const char *method_name,
- lldb_private::SymbolContext *sym_ctx) {
- PyErr_Cleaner py_err_cleaner(false);
- PythonObject self(PyRefType::Borrowed, static_cast<PyObject *>(implementor));
- auto pfunc = self.ResolveName<PythonCallable>(method_name);
-
- if (!pfunc.IsAllocated())
- return 0;
-
- PythonObject result = sym_ctx ? pfunc(SWIGBridge::ToSWIGWrapper(*sym_ctx)) : pfunc();
-
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- return 0;
- }
-
- // The callback will return a bool, but we're need to also return ints
- // so we're squirrelling the bool through as an int... And if you return
- // nothing, we'll continue.
- if (strcmp(method_name, "__callback__") == 0) {
- if (result.get() == Py_False)
- return 0;
- else
- return 1;
- }
-
- long long ret_val = unwrapOrSetPythonException(As<long long>(result));
-
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- return 0;
- }
-
- return ret_val;
-}
-
// wrapper that calls an optional instance member of an object taking no
// arguments
static PyObject *LLDBSwigPython_CallOptionalMember(
@@ -554,6 +482,18 @@ void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject * dat
return sb_ptr;
}
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject * data) {
+ lldb::SBSymbolContext *sb_ptr = nullptr;
+
+ int valid_cast =
+ SWIG_ConvertPtr(data, (void **)&sb_ptr, SWIGTYPE_p_lldb__SBSymbolContext, 0);
+
+ if (valid_cast == -1)
+ return NULL;
+
+ return sb_ptr;
+}
+
void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject * data) {
lldb::SBValue *sb_ptr = NULL;
diff --git a/lldb/cmake/modules/LLDBConfig.cmake b/lldb/cmake/modules/LLDBConfig.cmake
index 8c30b6e..fc84e58 100644
--- a/lldb/cmake/modules/LLDBConfig.cmake
+++ b/lldb/cmake/modules/LLDBConfig.cmake
@@ -323,4 +323,30 @@ else()
set(LLDB_CAN_USE_DEBUGSERVER OFF)
endif()
+# In a cross-compile build, we need to skip building the generated
+# lldb-rpc sources in the first phase of host build so that they can
+# get built using the just-built Clang toolchain in the second phase.
+if (NOT DEFINED LLDB_CAN_USE_LLDB_RPC_SERVER)
+ set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
+else()
+ if ((CMAKE_CROSSCOMPILING OR LLVM_HOST_TRIPLE MATCHES "${LLVM_DEFAULT_TARGET_TRIPLE}") AND
+ CMAKE_SYSTEM_NAME MATCHES "AIX|Android|Darwin|FreeBSD|Linux|NetBSD|OpenBSD|Windows")
+ set(LLDB_CAN_USE_LLDB_RPC_SERVER ON)
+ else()
+ set(LLDB_CAN_USE_LLDB_RPC_SERVER OFF)
+ endif()
+endif()
+
+
+if (NOT DEFINED LLDB_BUILD_LLDBRPC)
+ set(LLDB_BUILD_LLDBRPC OFF)
+else()
+ if (CMAKE_CROSSCOMPILING)
+ set(LLDB_BUILD_LLDBRPC OFF CACHE BOOL "")
+ get_host_tool_path(lldb-rpc-gen LLDB_RPC_GEN_EXE lldb_rpc_gen_exe lldb_rpc_gen_target)
+ else()
+ set(LLDB_BUILD_LLDBRPC ON CACHE BOOL "")
+ endif()
+endif()
+
include(LLDBGenerateConfig)
diff --git a/lldb/docs/index.rst b/lldb/docs/index.rst
index d49d0d8..a981c0a 100644
--- a/lldb/docs/index.rst
+++ b/lldb/docs/index.rst
@@ -86,6 +86,7 @@ current state, follow the links to their respective issues:
* `RISC-V <https://github.com/llvm/llvm-project/issues/55383>`_
* `LoongArch <https://github.com/llvm/llvm-project/issues/112693>`_
+* `WebAssembly <https://github.com/llvm/llvm-project/issues/150449>`_
Get Involved
------------
diff --git a/lldb/docs/resources/build.rst b/lldb/docs/resources/build.rst
index 4bbec89..0db8c92 100644
--- a/lldb/docs/resources/build.rst
+++ b/lldb/docs/resources/build.rst
@@ -204,12 +204,13 @@ checked out above, but now we will have multiple build-trees:
Run CMake with ``-B`` pointing to a new directory for the provided
build-tree\ :sup:`1` and the positional argument pointing to the ``llvm``
-directory in the source-tree. Note that we leave out LLDB here and only include
+directory in the source-tree.\ :sup:`2` Note that we leave out LLDB here and only include
Clang. Then we build the ``ALL`` target with ninja:
::
$ cmake -B /path/to/llvm-build -G Ninja \
+ -DCMAKE_BUILD_TYPE=[<build type>] \
-DLLVM_ENABLE_PROJECTS=clang \
-DCMAKE_BUILD_TYPE=Release \
[<more cmake options>] /path/to/llvm-project/llvm
@@ -238,6 +239,8 @@ remove it from the Ninja command.
#. The ``-B`` argument was undocumented for a while and is only officially
supported since `CMake version 3.14
<https://cmake.org/cmake/help/v3.14/release/3.14.html#command-line>`_
+ #. If you want to have a standalone LLDB build with tests enabled, you also
+ need to pass in ``-DLLVM_ENABLE_RUNTIME='libcxx;libcxxabi;libunwind'`` to your CMake invocation when configuring your LLVM standalone build.
.. _CommonCMakeOptions:
diff --git a/lldb/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md
index 80c6809..41628cf 100644
--- a/lldb/docs/resources/lldbgdbremote.md
+++ b/lldb/docs/resources/lldbgdbremote.md
@@ -1998,6 +1998,22 @@ threads (live system debug) / cores (JTAG) in your program have
stopped and allows LLDB to display and control your program
correctly.
+## qWasmCallStack
+
+Get the Wasm call stack for the given thread id. This returns a hex-encoded
+list of PC values, one for each frame of the call stack. To match the Wasm
+specification, the addresses are encoded in little endian byte order, even if
+the endian of the Wasm runtime's host is not little endian.
+
+```
+send packet: $qWasmCallStack:202dbe040#08
+read packet: $9c01000000000040e501000000000040fe01000000000040#
+```
+
+**Priority to Implement:** Only required for Wasm support. This packed is
+supported by the [WAMR](https://github.com/bytecodealliance/wasm-micro-runtime)
+and [V8](https://v8.dev) Wasm runtimes.
+
## qWatchpointSupportInfo
Get the number of hardware watchpoints available on the remote target.
diff --git a/lldb/include/lldb/API/SBSymbolContext.h b/lldb/include/lldb/API/SBSymbolContext.h
index ae9fd84..128b0b6 100644
--- a/lldb/include/lldb/API/SBSymbolContext.h
+++ b/lldb/include/lldb/API/SBSymbolContext.h
@@ -80,6 +80,8 @@ protected:
lldb_private::SymbolContext *get() const;
+ friend class lldb_private::ScriptInterpreter;
+
private:
std::unique_ptr<lldb_private::SymbolContext> m_opaque_up;
};
diff --git a/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h b/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h
index 0e4a1d7..0322fd9 100644
--- a/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h
+++ b/lldb/include/lldb/Breakpoint/BreakpointResolverScripted.h
@@ -12,6 +12,7 @@
#include "lldb/Breakpoint/BreakpointResolver.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StructuredDataImpl.h"
+#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
#include "lldb/lldb-forward.h"
namespace lldb_private {
@@ -64,7 +65,8 @@ private:
std::string m_class_name;
lldb::SearchDepth m_depth;
StructuredDataImpl m_args;
- StructuredData::GenericSP m_implementation_sp;
+ Status m_error;
+ lldb::ScriptedBreakpointInterfaceSP m_interface_sp;
BreakpointResolverScripted(const BreakpointResolverScripted &) = delete;
const BreakpointResolverScripted &
diff --git a/lldb/include/lldb/Core/ModuleList.h b/lldb/include/lldb/Core/ModuleList.h
index 909ee08..d5e291f3 100644
--- a/lldb/include/lldb/Core/ModuleList.h
+++ b/lldb/include/lldb/Core/ModuleList.h
@@ -17,6 +17,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/lldb-enumerations.h"
#include "lldb/lldb-forward.h"
+#include "lldb/lldb-private-enumerations.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/DenseSet.h"
@@ -488,8 +489,9 @@ public:
/// be non-null.
///
/// This function is thread-safe.
- void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const
- &callback) const;
+ void
+ ForEach(std::function<IterationAction(const lldb::ModuleSP &module_sp)> const
+ &callback) const;
/// Returns true if 'callback' returns true for one of the modules
/// in this ModuleList.
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h
new file mode 100644
index 0000000..28d6ed9
--- /dev/null
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h
@@ -0,0 +1,32 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SCRIPTEDBREAKPOINTINTERFACE_H
+#define LLDB_INTERPRETER_INTERFACES_SCRIPTEDBREAKPOINTINTERFACE_H
+
+#include "ScriptedInterface.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/lldb-private.h"
+
+namespace lldb_private {
+class ScriptedBreakpointInterface : public ScriptedInterface {
+public:
+ virtual llvm::Expected<StructuredData::GenericSP>
+ CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp,
+ const StructuredDataImpl &args_sp) = 0;
+
+ /// "ResolverCallback" will get called when a new module is loaded. The
+ /// new module information is passed in sym_ctx. The Resolver will add
+ /// any breakpoint locations it found in that module.
+ virtual bool ResolverCallback(SymbolContext sym_ctx) { return true; }
+ virtual lldb::SearchDepth GetDepth() { return lldb::eSearchDepthModule; }
+ virtual std::optional<std::string> GetShortHelp() { return nullptr; }
+};
+} // namespace lldb_private
+
+#endif // LLDB_INTERPRETER_INTERFACES_SCRIPTEDSTOPHOOKINTERFACE_H
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index f1c3eef..dffb9b8 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -18,6 +18,7 @@
#include "lldb/API/SBLaunchInfo.h"
#include "lldb/API/SBMemoryRegionInfo.h"
#include "lldb/API/SBStream.h"
+#include "lldb/API/SBSymbolContext.h"
#include "lldb/Breakpoint/BreakpointOptions.h"
#include "lldb/Core/PluginInterface.h"
#include "lldb/Core/SearchFilter.h"
@@ -29,6 +30,7 @@
#include "lldb/Interpreter/Interfaces/ScriptedProcessInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedThreadInterface.h"
#include "lldb/Interpreter/ScriptObject.h"
+#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Utility/Broadcaster.h"
#include "lldb/Utility/Status.h"
#include "lldb/Utility/StructuredData.h"
@@ -257,26 +259,6 @@ public:
return false;
}
- virtual StructuredData::GenericSP
- CreateScriptedBreakpointResolver(const char *class_name,
- const StructuredDataImpl &args_data,
- lldb::BreakpointSP &bkpt_sp) {
- return StructuredData::GenericSP();
- }
-
- virtual bool
- ScriptedBreakpointResolverSearchCallback(StructuredData::GenericSP implementor_sp,
- SymbolContext *sym_ctx)
- {
- return false;
- }
-
- virtual lldb::SearchDepth
- ScriptedBreakpointResolverSearchDepth(StructuredData::GenericSP implementor_sp)
- {
- return lldb::eSearchDepthModule;
- }
-
virtual StructuredData::ObjectSP
LoadPluginModule(const FileSpec &file_spec, lldb_private::Status &error) {
return StructuredData::ObjectSP();
@@ -566,6 +548,11 @@ public:
return {};
}
+ virtual lldb::ScriptedBreakpointInterfaceSP
+ CreateScriptedBreakpointInterface() {
+ return {};
+ }
+
virtual StructuredData::ObjectSP
CreateStructuredDataFromScriptObject(ScriptObject obj) {
return {};
@@ -580,6 +567,9 @@ public:
lldb::StreamSP GetOpaqueTypeFromSBStream(const lldb::SBStream &stream) const;
+ SymbolContext
+ GetOpaqueTypeFromSBSymbolContext(const lldb::SBSymbolContext &sym_ctx) const;
+
lldb::BreakpointSP
GetOpaqueTypeFromSBBreakpoint(const lldb::SBBreakpoint &breakpoint) const;
diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h
index 637b077..7e66e31 100644
--- a/lldb/include/lldb/Target/Process.h
+++ b/lldb/include/lldb/Target/Process.h
@@ -2619,7 +2619,7 @@ void PruneThreadPlans();
void ResetExtendedCrashInfoDict() {
// StructuredData::Dictionary is add only, so we have to make a new one:
- m_crash_info_dict_sp.reset(new StructuredData::Dictionary());
+ m_crash_info_dict_sp = std::make_shared<StructuredData::Dictionary>();
}
size_t AddImageToken(lldb::addr_t image_ptr);
diff --git a/lldb/include/lldb/Target/StackFrameList.h b/lldb/include/lldb/Target/StackFrameList.h
index 8a66296..e5a6e942 100644
--- a/lldb/include/lldb/Target/StackFrameList.h
+++ b/lldb/include/lldb/Target/StackFrameList.h
@@ -174,6 +174,11 @@ protected:
/// change the frame if this is the first time GetSelectedFrame is called.
std::optional<uint32_t> m_selected_frame_idx;
+ /// Protect access to m_selected_frame_idx. Always acquire after m_list_mutex
+ /// to avoid lock inversion. A recursive mutex because GetSelectedFrameIndex
+ /// may indirectly call SetSelectedFrame.
+ std::recursive_mutex m_selected_frame_mutex;
+
/// The number of concrete frames fetched while filling the frame list. This
/// is only used when synthetic frames are enabled.
uint32_t m_concrete_frames_fetched;
diff --git a/lldb/include/lldb/lldb-forward.h b/lldb/include/lldb/lldb-forward.h
index 2bc85a2..483dce9 100644
--- a/lldb/include/lldb/lldb-forward.h
+++ b/lldb/include/lldb/lldb-forward.h
@@ -188,6 +188,7 @@ class Scalar;
class ScriptInterpreter;
class ScriptInterpreterLocker;
class ScriptedMetadata;
+class ScriptedBreakpointInterface;
class ScriptedPlatformInterface;
class ScriptedProcessInterface;
class ScriptedStopHookInterface;
@@ -418,6 +419,8 @@ typedef std::shared_ptr<lldb_private::ScriptedThreadInterface>
ScriptedThreadInterfaceSP;
typedef std::shared_ptr<lldb_private::ScriptedThreadPlanInterface>
ScriptedThreadPlanInterfaceSP;
+typedef std::shared_ptr<lldb_private::ScriptedBreakpointInterface>
+ ScriptedBreakpointInterfaceSP;
typedef std::shared_ptr<lldb_private::Section> SectionSP;
typedef std::unique_ptr<lldb_private::SectionList> SectionListUP;
typedef std::weak_ptr<lldb_private::Section> SectionWP;
diff --git a/lldb/packages/Python/lldbsuite/test/dotest.py b/lldb/packages/Python/lldbsuite/test/dotest.py
index 90c8e32..24236e7 100644
--- a/lldb/packages/Python/lldbsuite/test/dotest.py
+++ b/lldb/packages/Python/lldbsuite/test/dotest.py
@@ -294,9 +294,11 @@ def parseOptionsAndInitTestdirs():
"Custom libc++ requires both --libcxx-include-dir and --libcxx-library-dir"
)
sys.exit(-1)
- configuration.libcxx_include_dir = args.libcxx_include_dir
- configuration.libcxx_include_target_dir = args.libcxx_include_target_dir
- configuration.libcxx_library_dir = args.libcxx_library_dir
+ else:
+ configuration.libcxx_include_dir = args.libcxx_include_dir
+ configuration.libcxx_include_target_dir = args.libcxx_include_target_dir
+ configuration.libcxx_library_dir = args.libcxx_library_dir
+
configuration.cmake_build_type = args.cmake_build_type.lower()
if args.channels:
diff --git a/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py b/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
index 459460b..599f787 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbgdbclient.py
@@ -45,7 +45,7 @@ class GDBRemoteTestBase(TestBase):
self.yaml2obj(yaml_path, obj_path)
return self.dbg.CreateTarget(obj_path)
- def connect(self, target):
+ def connect(self, target, plugin="gdb-remote"):
"""
Create a process by connecting to the mock GDB server.
@@ -54,7 +54,7 @@ class GDBRemoteTestBase(TestBase):
listener = self.dbg.GetListener()
error = lldb.SBError()
process = target.ConnectRemote(
- listener, self.server.get_connect_url(), "gdb-remote", error
+ listener, self.server.get_connect_url(), plugin, error
)
self.assertTrue(error.Success(), error.description)
self.assertTrue(process, PROCESS_IS_VALID)
diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py
index 63fadb5..a74961e 100644
--- a/lldb/packages/Python/lldbsuite/test/lldbtest.py
+++ b/lldb/packages/Python/lldbsuite/test/lldbtest.py
@@ -1380,6 +1380,9 @@ class Base(unittest.TestCase):
def isAArch64MTE(self):
return self.isAArch64() and "mte" in self.getCPUInfo()
+ def isAArch64MTEStoreOnly(self):
+ return self.isAArch64() and "mtestoreonly" in self.getCPUInfo()
+
def isAArch64GCS(self):
return self.isAArch64() and "gcs" in self.getCPUInfo()
diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt
index 197c98c..fdd6b3b 100644
--- a/lldb/source/API/CMakeLists.txt
+++ b/lldb/source/API/CMakeLists.txt
@@ -302,7 +302,7 @@ list(REMOVE_ITEM root_public_headers ${root_private_headers})
find_program(unifdef_EXECUTABLE unifdef)
-add_custom_target(liblldb-header-staging DEPENDS ${lldb_staged_headers} ${lldb_header_staging_dir}/lldb-defines.h)
+add_custom_target(liblldb-header-staging)
if (LLDB_BUILD_FRAMEWORK)
add_custom_target(lldb-framework-fixup-all-headers)
@@ -326,6 +326,9 @@ foreach(header
set(copy_command ${CMAKE_COMMAND} -E copy ${header} ${staged_header})
endif()
+ add_custom_target(liblldb-stage-header-${basename} DEPENDS ${staged_header})
+ add_dependencies(liblldb-stage-header-${basename} lldb-sbapi-dwarf-enums)
+ add_dependencies(liblldb-header-staging liblldb-stage-header-${basename})
add_custom_command(
DEPENDS ${header} OUTPUT ${staged_header}
COMMAND ${copy_command}
@@ -337,6 +340,7 @@ foreach(header
set(output_header $<TARGET_FILE_DIR:liblldb>/Headers/${basename})
add_custom_target(lldb-framework-fixup-header-${basename} DEPENDS ${staged_header})
+ add_dependencies(lldb-framework-fixup-header-${basename} liblldb-stage-header-${basename})
add_dependencies(lldb-framework-fixup-all-headers lldb-framework-fixup-header-${basename})
add_custom_command(TARGET lldb-framework-fixup-header-${basename} POST_BUILD
diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp
index 00f2871..f58902d 100644
--- a/lldb/source/API/SBType.cpp
+++ b/lldb/source/API/SBType.cpp
@@ -184,7 +184,7 @@ SBType SBType::GetPointerType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointerType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetPointerType()));
}
SBType SBType::GetPointeeType() {
@@ -192,7 +192,7 @@ SBType SBType::GetPointeeType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetPointeeType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetPointeeType()));
}
SBType SBType::GetReferenceType() {
@@ -200,7 +200,7 @@ SBType SBType::GetReferenceType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetReferenceType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetReferenceType()));
}
SBType SBType::GetTypedefedType() {
@@ -208,7 +208,7 @@ SBType SBType::GetTypedefedType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetTypedefedType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetTypedefedType()));
}
SBType SBType::GetDereferencedType() {
@@ -216,7 +216,7 @@ SBType SBType::GetDereferencedType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetDereferencedType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetDereferencedType()));
}
SBType SBType::GetArrayElementType() {
@@ -224,8 +224,8 @@ SBType SBType::GetArrayElementType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(
- m_opaque_sp->GetCompilerType(true).GetArrayElementType(nullptr))));
+ return SBType(std::make_shared<TypeImpl>(
+ m_opaque_sp->GetCompilerType(true).GetArrayElementType(nullptr)));
}
SBType SBType::GetArrayType(uint64_t size) {
@@ -233,8 +233,8 @@ SBType SBType::GetArrayType(uint64_t size) {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(
- new TypeImpl(m_opaque_sp->GetCompilerType(true).GetArrayType(size))));
+ return SBType(std::make_shared<TypeImpl>(
+ m_opaque_sp->GetCompilerType(true).GetArrayType(size)));
}
SBType SBType::GetVectorElementType() {
@@ -245,7 +245,7 @@ SBType SBType::GetVectorElementType() {
CompilerType vector_element_type;
if (m_opaque_sp->GetCompilerType(true).IsVectorType(&vector_element_type,
nullptr))
- type_sb.SetSP(TypeImplSP(new TypeImpl(vector_element_type)));
+ type_sb.SetSP(std::make_shared<TypeImpl>(vector_element_type));
}
return type_sb;
}
@@ -421,14 +421,14 @@ lldb::SBType SBType::GetUnqualifiedType() {
if (!IsValid())
return SBType();
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetUnqualifiedType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetUnqualifiedType()));
}
lldb::SBType SBType::GetCanonicalType() {
LLDB_INSTRUMENT_VA(this);
if (IsValid())
- return SBType(TypeImplSP(new TypeImpl(m_opaque_sp->GetCanonicalType())));
+ return SBType(std::make_shared<TypeImpl>(m_opaque_sp->GetCanonicalType()));
return SBType();
}
@@ -508,7 +508,7 @@ SBTypeMember SBType::GetDirectBaseClassAtIndex(uint32_t idx) {
idx, &bit_offset);
if (base_class_type.IsValid())
sb_type_member.reset(new TypeMemberImpl(
- TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
+ std::make_shared<TypeImpl>(base_class_type), bit_offset));
}
return sb_type_member;
}
@@ -524,7 +524,7 @@ SBTypeMember SBType::GetVirtualBaseClassAtIndex(uint32_t idx) {
idx, &bit_offset);
if (base_class_type.IsValid())
sb_type_member.reset(new TypeMemberImpl(
- TypeImplSP(new TypeImpl(base_class_type)), bit_offset));
+ std::make_shared<TypeImpl>(base_class_type), bit_offset));
}
return sb_type_member;
}
@@ -546,16 +546,15 @@ SBTypeEnumMemberList SBType::GetEnumMembers() {
if (IsValid()) {
CompilerType this_type(m_opaque_sp->GetCompilerType(true));
if (this_type.IsValid()) {
- this_type.ForEachEnumerator([&sb_enum_member_list](
- const CompilerType &integer_type,
- ConstString name,
- const llvm::APSInt &value) -> bool {
- SBTypeEnumMember enum_member(
- lldb::TypeEnumMemberImplSP(new TypeEnumMemberImpl(
- lldb::TypeImplSP(new TypeImpl(integer_type)), name, value)));
- sb_enum_member_list.Append(enum_member);
- return true; // Keep iterating
- });
+ this_type.ForEachEnumerator(
+ [&sb_enum_member_list](const CompilerType &integer_type,
+ ConstString name,
+ const llvm::APSInt &value) -> bool {
+ SBTypeEnumMember enum_member(std::make_shared<TypeEnumMemberImpl>(
+ std::make_shared<TypeImpl>(integer_type), name, value));
+ sb_enum_member_list.Append(enum_member);
+ return true; // Keep iterating
+ });
}
}
return sb_enum_member_list;
@@ -578,9 +577,9 @@ SBTypeMember SBType::GetFieldAtIndex(uint32_t idx) {
ConstString name;
if (!name_sstr.empty())
name.SetCString(name_sstr.c_str());
- sb_type_member.reset(
- new TypeMemberImpl(TypeImplSP(new TypeImpl(field_type)), bit_offset,
- name, bitfield_bit_size, is_bitfield));
+ sb_type_member.reset(new TypeMemberImpl(
+ std::make_shared<TypeImpl>(field_type), bit_offset, name,
+ bitfield_bit_size, is_bitfield));
}
}
}
@@ -978,7 +977,7 @@ SBType SBTypeMemberFunction::GetType() {
SBType sb_type;
if (m_opaque_sp) {
- sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetType())));
+ sb_type.SetSP(std::make_shared<TypeImpl>(m_opaque_sp->GetType()));
}
return sb_type;
}
@@ -988,7 +987,7 @@ lldb::SBType SBTypeMemberFunction::GetReturnType() {
SBType sb_type;
if (m_opaque_sp) {
- sb_type.SetSP(lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetReturnType())));
+ sb_type.SetSP(std::make_shared<TypeImpl>(m_opaque_sp->GetReturnType()));
}
return sb_type;
}
@@ -1007,7 +1006,7 @@ lldb::SBType SBTypeMemberFunction::GetArgumentTypeAtIndex(uint32_t i) {
SBType sb_type;
if (m_opaque_sp) {
sb_type.SetSP(
- lldb::TypeImplSP(new TypeImpl(m_opaque_sp->GetArgumentAtIndex(i))));
+ std::make_shared<TypeImpl>(m_opaque_sp->GetArgumentAtIndex(i)));
}
return sb_type;
}
diff --git a/lldb/source/API/SBTypeFilter.cpp b/lldb/source/API/SBTypeFilter.cpp
index f1b5bc9..e10d269 100644
--- a/lldb/source/API/SBTypeFilter.cpp
+++ b/lldb/source/API/SBTypeFilter.cpp
@@ -19,7 +19,7 @@ using namespace lldb_private;
SBTypeFilter::SBTypeFilter() { LLDB_INSTRUMENT_VA(this); }
SBTypeFilter::SBTypeFilter(uint32_t options)
- : m_opaque_sp(TypeFilterImplSP(new TypeFilterImpl(options))) {
+ : m_opaque_sp(std::make_shared<TypeFilterImpl>(options)) {
LLDB_INSTRUMENT_VA(this, options);
}
diff --git a/lldb/source/API/SBTypeNameSpecifier.cpp b/lldb/source/API/SBTypeNameSpecifier.cpp
index 308b1cd..dd81720 100644
--- a/lldb/source/API/SBTypeNameSpecifier.cpp
+++ b/lldb/source/API/SBTypeNameSpecifier.cpp
@@ -38,8 +38,8 @@ SBTypeNameSpecifier::SBTypeNameSpecifier(SBType type) {
LLDB_INSTRUMENT_VA(this, type);
if (type.IsValid())
- m_opaque_sp = TypeNameSpecifierImplSP(
- new TypeNameSpecifierImpl(type.m_opaque_sp->GetCompilerType(true)));
+ m_opaque_sp = std::make_shared<TypeNameSpecifierImpl>(
+ type.m_opaque_sp->GetCompilerType(true));
}
SBTypeNameSpecifier::SBTypeNameSpecifier(const lldb::SBTypeNameSpecifier &rhs)
diff --git a/lldb/source/API/SBTypeSynthetic.cpp b/lldb/source/API/SBTypeSynthetic.cpp
index 19a4c53..5ebc884 100644
--- a/lldb/source/API/SBTypeSynthetic.cpp
+++ b/lldb/source/API/SBTypeSynthetic.cpp
@@ -24,8 +24,8 @@ SBTypeSynthetic SBTypeSynthetic::CreateWithClassName(const char *data,
if (!data || data[0] == 0)
return SBTypeSynthetic();
- return SBTypeSynthetic(ScriptedSyntheticChildrenSP(
- new ScriptedSyntheticChildren(options, data, "")));
+ return SBTypeSynthetic(
+ std::make_shared<ScriptedSyntheticChildren>(options, data, ""));
}
SBTypeSynthetic SBTypeSynthetic::CreateWithScriptCode(const char *data,
@@ -34,8 +34,8 @@ SBTypeSynthetic SBTypeSynthetic::CreateWithScriptCode(const char *data,
if (!data || data[0] == 0)
return SBTypeSynthetic();
- return SBTypeSynthetic(ScriptedSyntheticChildrenSP(
- new ScriptedSyntheticChildren(options, "", data)));
+ return SBTypeSynthetic(
+ std::make_shared<ScriptedSyntheticChildren>(options, "", data));
}
SBTypeSynthetic::SBTypeSynthetic(const lldb::SBTypeSynthetic &rhs)
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index d878eb4..e300ece 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -1120,11 +1120,11 @@ void SBValue::SetSP(const lldb::ValueObjectSP &sp) {
lldb::DynamicValueType use_dynamic = target_sp->GetPreferDynamicValue();
bool use_synthetic =
target_sp->TargetProperties::GetEnableSyntheticValue();
- m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic));
+ m_opaque_sp = std::make_shared<ValueImpl>(sp, use_dynamic, use_synthetic);
} else
- m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, true));
+ m_opaque_sp = std::make_shared<ValueImpl>(sp, eNoDynamicValues, true);
} else
- m_opaque_sp = ValueImplSP(new ValueImpl(sp, eNoDynamicValues, false));
+ m_opaque_sp = std::make_shared<ValueImpl>(sp, eNoDynamicValues, false);
}
void SBValue::SetSP(const lldb::ValueObjectSP &sp,
@@ -1155,14 +1155,14 @@ void SBValue::SetSP(const lldb::ValueObjectSP &sp, bool use_synthetic) {
void SBValue::SetSP(const lldb::ValueObjectSP &sp,
lldb::DynamicValueType use_dynamic, bool use_synthetic) {
- m_opaque_sp = ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic));
+ m_opaque_sp = std::make_shared<ValueImpl>(sp, use_dynamic, use_synthetic);
}
void SBValue::SetSP(const lldb::ValueObjectSP &sp,
lldb::DynamicValueType use_dynamic, bool use_synthetic,
const char *name) {
m_opaque_sp =
- ValueImplSP(new ValueImpl(sp, use_dynamic, use_synthetic, name));
+ std::make_shared<ValueImpl>(sp, use_dynamic, use_synthetic, name);
}
bool SBValue::GetExpressionPath(SBStream &description) {
diff --git a/lldb/source/Breakpoint/Breakpoint.cpp b/lldb/source/Breakpoint/Breakpoint.cpp
index d757bc4..1544bf8 100644
--- a/lldb/source/Breakpoint/Breakpoint.cpp
+++ b/lldb/source/Breakpoint/Breakpoint.cpp
@@ -83,8 +83,7 @@ StructuredData::ObjectSP Breakpoint::SerializeToStructuredData() {
if (!m_name_list.empty()) {
StructuredData::ArraySP names_array_sp(new StructuredData::Array());
for (auto name : m_name_list) {
- names_array_sp->AddItem(
- StructuredData::StringSP(new StructuredData::String(name)));
+ names_array_sp->AddItem(std::make_shared<StructuredData::String>(name));
}
breakpoint_contents_sp->AddItem(Breakpoint::GetKey(OptionNames::Names),
names_array_sp);
diff --git a/lldb/source/Breakpoint/BreakpointResolverName.cpp b/lldb/source/Breakpoint/BreakpointResolverName.cpp
index edde1c9..21024a4 100644
--- a/lldb/source/Breakpoint/BreakpointResolverName.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverName.cpp
@@ -195,10 +195,10 @@ StructuredData::ObjectSP BreakpointResolverName::SerializeToStructuredData() {
StructuredData::ArraySP names_sp(new StructuredData::Array());
StructuredData::ArraySP name_masks_sp(new StructuredData::Array());
for (auto lookup : m_lookups) {
- names_sp->AddItem(StructuredData::StringSP(
- new StructuredData::String(lookup.GetName().GetStringRef())));
- name_masks_sp->AddItem(StructuredData::UnsignedIntegerSP(
- new StructuredData::UnsignedInteger(lookup.GetNameTypeMask())));
+ names_sp->AddItem(std::make_shared<StructuredData::String>(
+ lookup.GetName().GetStringRef()));
+ name_masks_sp->AddItem(std::make_shared<StructuredData::UnsignedInteger>(
+ lookup.GetNameTypeMask()));
}
options_dict_sp->AddItem(GetKey(OptionNames::SymbolNameArray), names_sp);
options_dict_sp->AddItem(GetKey(OptionNames::NameMaskArray), name_masks_sp);
diff --git a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp
index 2457052..701caba 100644
--- a/lldb/source/Breakpoint/BreakpointResolverScripted.cpp
+++ b/lldb/source/Breakpoint/BreakpointResolverScripted.cpp
@@ -35,7 +35,7 @@ BreakpointResolverScripted::BreakpointResolverScripted(
void BreakpointResolverScripted::CreateImplementationIfNeeded(
BreakpointSP breakpoint_sp) {
- if (m_implementation_sp)
+ if (m_interface_sp)
return;
if (m_class_name.empty())
@@ -50,8 +50,27 @@ void BreakpointResolverScripted::CreateImplementationIfNeeded(
if (!script_interp)
return;
- m_implementation_sp = script_interp->CreateScriptedBreakpointResolver(
- m_class_name.c_str(), m_args, breakpoint_sp);
+ m_interface_sp = script_interp->CreateScriptedBreakpointInterface();
+ if (!m_interface_sp) {
+ m_error = Status::FromErrorStringWithFormat(
+ "BreakpointResolverScripted::%s () - ERROR: %s", __FUNCTION__,
+ "Script interpreter couldn't create Scripted Breakpoint Interface");
+ return;
+ }
+
+ auto obj_or_err =
+ m_interface_sp->CreatePluginObject(m_class_name, breakpoint_sp, m_args);
+ if (!obj_or_err) {
+ m_error = Status::FromError(obj_or_err.takeError());
+ return;
+ }
+
+ StructuredData::ObjectSP object_sp = *obj_or_err;
+ if (!object_sp || !object_sp->IsValid()) {
+ m_error = Status::FromErrorStringWithFormat(
+ "ScriptedBreakpoint::%s () - ERROR: %s", __FUNCTION__,
+ "Failed to create valid script object");
+ }
}
void BreakpointResolverScripted::NotifyBreakpointSet() {
@@ -104,13 +123,10 @@ ScriptInterpreter *BreakpointResolverScripted::GetScriptInterpreter() {
Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
SearchFilter &filter, SymbolContext &context, Address *addr) {
bool should_continue = true;
- if (!m_implementation_sp)
+ if (!m_interface_sp)
return Searcher::eCallbackReturnStop;
- ScriptInterpreter *interp = GetScriptInterpreter();
- should_continue = interp->ScriptedBreakpointResolverSearchCallback(
- m_implementation_sp,
- &context);
+ should_continue = m_interface_sp->ResolverCallback(context);
if (should_continue)
return Searcher::eCallbackReturnContinue;
@@ -120,25 +136,21 @@ Searcher::CallbackReturn BreakpointResolverScripted::SearchCallback(
lldb::SearchDepth
BreakpointResolverScripted::GetDepth() {
lldb::SearchDepth depth = lldb::eSearchDepthModule;
- if (m_implementation_sp) {
- ScriptInterpreter *interp = GetScriptInterpreter();
- depth = interp->ScriptedBreakpointResolverSearchDepth(
- m_implementation_sp);
- }
+ if (m_interface_sp)
+ depth = m_interface_sp->GetDepth();
+
return depth;
}
void BreakpointResolverScripted::GetDescription(Stream *s) {
StructuredData::GenericSP generic_sp;
- std::string short_help;
+ std::optional<std::string> short_help;
- if (m_implementation_sp) {
- ScriptInterpreter *interp = GetScriptInterpreter();
- interp->GetShortHelpForCommandObject(m_implementation_sp,
- short_help);
+ if (m_interface_sp) {
+ short_help = m_interface_sp->GetShortHelp();
}
- if (!short_help.empty())
- s->PutCString(short_help.c_str());
+ if (short_help && !short_help->empty())
+ s->PutCString(short_help->c_str());
else
s->Printf("python class = %s", m_class_name.c_str());
}
diff --git a/lldb/source/Commands/CommandCompletions.cpp b/lldb/source/Commands/CommandCompletions.cpp
index 3e22309..b2fc893 100644
--- a/lldb/source/Commands/CommandCompletions.cpp
+++ b/lldb/source/Commands/CommandCompletions.cpp
@@ -571,7 +571,7 @@ void CommandCompletions::ModuleUUIDs(CommandInterpreter &interpreter,
lldb::eDescriptionLevelInitial);
request.TryCompleteCurrentArg(module->GetUUID().GetAsString(),
strm.GetString());
- return true;
+ return IterationAction::Continue;
});
}
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp
index 10dc273..3049eb8 100644
--- a/lldb/source/Commands/CommandObjectCommands.cpp
+++ b/lldb/source/Commands/CommandObjectCommands.cpp
@@ -25,6 +25,7 @@
#include "lldb/Utility/Args.h"
#include "lldb/Utility/StringList.h"
#include "llvm/ADT/StringRef.h"
+#include <memory>
#include <optional>
using namespace lldb;
@@ -467,7 +468,7 @@ protected:
// Verify & handle any options/arguments passed to the alias command
OptionArgVectorSP option_arg_vector_sp =
- OptionArgVectorSP(new OptionArgVector);
+ std::make_shared<OptionArgVector>();
const bool include_aliases = true;
// Look up the command using command's name first. This is to resolve
@@ -543,7 +544,7 @@ protected:
CommandObject *cmd_obj = command_obj_sp.get();
CommandObject *sub_cmd_obj = nullptr;
OptionArgVectorSP option_arg_vector_sp =
- OptionArgVectorSP(new OptionArgVector);
+ std::make_shared<OptionArgVector>();
while (cmd_obj->IsMultiwordObject() && !args.empty()) {
auto sub_command = args[0].ref();
@@ -2504,9 +2505,9 @@ protected:
CommandObjectSP new_cmd_sp;
if (m_options.m_class_name.empty()) {
- new_cmd_sp.reset(new CommandObjectPythonFunction(
+ new_cmd_sp = std::make_shared<CommandObjectPythonFunction>(
m_interpreter, m_cmd_name, m_options.m_funct_name,
- m_options.m_short_help, m_synchronicity, m_completion_type));
+ m_options.m_short_help, m_synchronicity, m_completion_type);
} else {
ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter();
if (!interpreter) {
@@ -2528,9 +2529,9 @@ protected:
if (!result.Succeeded())
return;
} else
- new_cmd_sp.reset(new CommandObjectScriptingObjectRaw(
+ new_cmd_sp = std::make_shared<CommandObjectScriptingObjectRaw>(
m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity,
- m_completion_type));
+ m_completion_type);
}
// Assume we're going to succeed...
diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp
index 7e42ef2..5692699 100644
--- a/lldb/source/Commands/CommandObjectFrame.cpp
+++ b/lldb/source/Commands/CommandObjectFrame.cpp
@@ -901,10 +901,9 @@ void CommandObjectFrameRecognizerAdd::DoExecute(Args &command,
StackFrameRecognizerSP(new ScriptedStackFrameRecognizer(
interpreter, m_options.m_class_name.c_str()));
if (m_options.m_regex) {
- auto module =
- RegularExpressionSP(new RegularExpression(m_options.m_module));
+ auto module = std::make_shared<RegularExpression>(m_options.m_module);
auto func =
- RegularExpressionSP(new RegularExpression(m_options.m_symbols.front()));
+ std::make_shared<RegularExpression>(m_options.m_symbols.front());
GetTarget().GetFrameRecognizerManager().AddRecognizer(
recognizer_sp, module, func, Mangled::NamePreference::ePreferDemangled,
m_options.m_first_instruction_only);
diff --git a/lldb/source/Core/IOHandlerCursesGUI.cpp b/lldb/source/Core/IOHandlerCursesGUI.cpp
index 7f0e0fc..3976630 100644
--- a/lldb/source/Core/IOHandlerCursesGUI.cpp
+++ b/lldb/source/Core/IOHandlerCursesGUI.cpp
@@ -22,6 +22,7 @@
#if defined(__APPLE__)
#include <deque>
#endif
+#include <memory>
#include <string>
#include "lldb/Core/Debugger.h"
@@ -6536,7 +6537,7 @@ public:
if (process && process->IsAlive() &&
StateIsStoppedState(process->GetState(), true)) {
if (submenus.size() == 7)
- menu.AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ menu.AddSubmenu(std::make_shared<Menu>(Menu::Type::Separator));
else if (submenus.size() > 8)
submenus.erase(submenus.begin() + 8, submenus.end());
@@ -6558,9 +6559,9 @@ public:
if (queue_name && queue_name[0])
thread_menu_title.Printf(" %s", queue_name);
}
- menu.AddSubmenu(
- MenuSP(new Menu(thread_menu_title.GetString().str().c_str(),
- nullptr, menu_char, thread_sp->GetID())));
+ menu.AddSubmenu(std::make_shared<Menu>(
+ thread_menu_title.GetString().str().c_str(), nullptr, menu_char,
+ thread_sp->GetID()));
}
} else if (submenus.size() > 7) {
// Remove the separator and any other thread submenu items that were
@@ -7573,70 +7574,67 @@ void IOHandlerCursesGUI::Activate() {
MenuSP exit_menuitem_sp(
new Menu("Exit", nullptr, 'x', ApplicationDelegate::eMenuID_LLDBExit));
exit_menuitem_sp->SetCannedResult(MenuActionResult::Quit);
- lldb_menu_sp->AddSubmenu(MenuSP(new Menu(
- "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout)));
- lldb_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ lldb_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "About LLDB", nullptr, 'a', ApplicationDelegate::eMenuID_LLDBAbout));
+ lldb_menu_sp->AddSubmenu(std::make_shared<Menu>(Menu::Type::Separator));
lldb_menu_sp->AddSubmenu(exit_menuitem_sp);
MenuSP target_menu_sp(new Menu("Target", "F2", KEY_F(2),
ApplicationDelegate::eMenuID_Target));
- target_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate)));
- target_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete)));
+ target_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Create", nullptr, 'c', ApplicationDelegate::eMenuID_TargetCreate));
+ target_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Delete", nullptr, 'd', ApplicationDelegate::eMenuID_TargetDelete));
MenuSP process_menu_sp(new Menu("Process", "F3", KEY_F(3),
ApplicationDelegate::eMenuID_Process));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach)));
- process_menu_sp->AddSubmenu(
- MenuSP(new Menu("Detach and resume", nullptr, 'd',
- ApplicationDelegate::eMenuID_ProcessDetachResume)));
- process_menu_sp->AddSubmenu(
- MenuSP(new Menu("Detach suspended", nullptr, 's',
- ApplicationDelegate::eMenuID_ProcessDetachSuspended)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(Menu::Type::Separator)));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Attach", nullptr, 'a', ApplicationDelegate::eMenuID_ProcessAttach));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Detach and resume", nullptr, 'd',
+ ApplicationDelegate::eMenuID_ProcessDetachResume));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Detach suspended", nullptr, 's',
+ ApplicationDelegate::eMenuID_ProcessDetachSuspended));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Launch", nullptr, 'l', ApplicationDelegate::eMenuID_ProcessLaunch));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(Menu::Type::Separator));
process_menu_sp->AddSubmenu(
- MenuSP(new Menu("Continue", nullptr, 'c',
- ApplicationDelegate::eMenuID_ProcessContinue)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt)));
- process_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill)));
+ std::make_shared<Menu>("Continue", nullptr, 'c',
+ ApplicationDelegate::eMenuID_ProcessContinue));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Halt", nullptr, 'h', ApplicationDelegate::eMenuID_ProcessHalt));
+ process_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Kill", nullptr, 'k', ApplicationDelegate::eMenuID_ProcessKill));
MenuSP thread_menu_sp(new Menu("Thread", "F4", KEY_F(4),
ApplicationDelegate::eMenuID_Thread));
- thread_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn)));
+ thread_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Step In", nullptr, 'i', ApplicationDelegate::eMenuID_ThreadStepIn));
thread_menu_sp->AddSubmenu(
- MenuSP(new Menu("Step Over", nullptr, 'v',
- ApplicationDelegate::eMenuID_ThreadStepOver)));
- thread_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut)));
+ std::make_shared<Menu>("Step Over", nullptr, 'v',
+ ApplicationDelegate::eMenuID_ThreadStepOver));
+ thread_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Step Out", nullptr, 'o', ApplicationDelegate::eMenuID_ThreadStepOut));
MenuSP view_menu_sp(
new Menu("View", "F5", KEY_F(5), ApplicationDelegate::eMenuID_View));
+ view_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Backtrace", nullptr, 't', ApplicationDelegate::eMenuID_ViewBacktrace));
+ view_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Registers", nullptr, 'r', ApplicationDelegate::eMenuID_ViewRegisters));
+ view_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource));
+ view_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "Variables", nullptr, 'v', ApplicationDelegate::eMenuID_ViewVariables));
view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Backtrace", nullptr, 't',
- ApplicationDelegate::eMenuID_ViewBacktrace)));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Registers", nullptr, 'r',
- ApplicationDelegate::eMenuID_ViewRegisters)));
- view_menu_sp->AddSubmenu(MenuSP(new Menu(
- "Source", nullptr, 's', ApplicationDelegate::eMenuID_ViewSource)));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Variables", nullptr, 'v',
- ApplicationDelegate::eMenuID_ViewVariables)));
- view_menu_sp->AddSubmenu(
- MenuSP(new Menu("Breakpoints", nullptr, 'b',
- ApplicationDelegate::eMenuID_ViewBreakpoints)));
+ std::make_shared<Menu>("Breakpoints", nullptr, 'b',
+ ApplicationDelegate::eMenuID_ViewBreakpoints));
MenuSP help_menu_sp(
new Menu("Help", "F6", KEY_F(6), ApplicationDelegate::eMenuID_Help));
- help_menu_sp->AddSubmenu(MenuSP(new Menu(
- "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp)));
+ help_menu_sp->AddSubmenu(std::make_shared<Menu>(
+ "GUI Help", nullptr, 'g', ApplicationDelegate::eMenuID_HelpGUIHelp));
m_app_up->Initialize();
WindowSP &main_window_sp = m_app_up->GetMainWindow();
diff --git a/lldb/source/Core/ModuleList.cpp b/lldb/source/Core/ModuleList.cpp
index d5ddf6e..d2e5be8 100644
--- a/lldb/source/Core/ModuleList.cpp
+++ b/lldb/source/Core/ModuleList.cpp
@@ -1077,12 +1077,12 @@ bool ModuleList::LoadScriptingResourcesInTarget(Target *target,
}
void ModuleList::ForEach(
- std::function<bool(const ModuleSP &module_sp)> const &callback) const {
+ std::function<IterationAction(const ModuleSP &module_sp)> const &callback)
+ const {
std::lock_guard<std::recursive_mutex> guard(m_modules_mutex);
for (const auto &module_sp : m_modules) {
assert(module_sp != nullptr);
- // If the callback returns false, then stop iterating and break out
- if (!callback(module_sp))
+ if (callback(module_sp) == IterationAction::Stop)
break;
}
}
diff --git a/lldb/source/DataFormatters/FormatManager.cpp b/lldb/source/DataFormatters/FormatManager.cpp
index 122f230..7862fb8 100644
--- a/lldb/source/DataFormatters/FormatManager.cpp
+++ b/lldb/source/DataFormatters/FormatManager.cpp
@@ -422,9 +422,8 @@ FormatManager::GetCategory(ConstString category_name, bool can_create) {
if (!can_create)
return lldb::TypeCategoryImplSP();
- m_categories_map.Add(
- category_name,
- lldb::TypeCategoryImplSP(new TypeCategoryImpl(this, category_name)));
+ m_categories_map.Add(category_name,
+ std::make_shared<TypeCategoryImpl>(this, category_name));
return GetCategory(category_name);
}
diff --git a/lldb/source/DataFormatters/TypeCategoryMap.cpp b/lldb/source/DataFormatters/TypeCategoryMap.cpp
index 719264b..9412dd3 100644
--- a/lldb/source/DataFormatters/TypeCategoryMap.cpp
+++ b/lldb/source/DataFormatters/TypeCategoryMap.cpp
@@ -19,7 +19,7 @@ TypeCategoryMap::TypeCategoryMap(IFormatChangeListener *lst)
: m_map_mutex(), listener(lst), m_map(), m_active_categories() {
ConstString default_cs("default");
lldb::TypeCategoryImplSP default_sp =
- lldb::TypeCategoryImplSP(new TypeCategoryImpl(listener, default_cs));
+ std::make_shared<TypeCategoryImpl>(listener, default_cs);
Add(default_cs, default_sp);
Enable(default_cs, First);
}
diff --git a/lldb/source/DataFormatters/ValueObjectPrinter.cpp b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
index 05fcc4d..c2f8bb3 100644
--- a/lldb/source/DataFormatters/ValueObjectPrinter.cpp
+++ b/lldb/source/DataFormatters/ValueObjectPrinter.cpp
@@ -16,6 +16,7 @@
#include "lldb/ValueObject/ValueObject.h"
#include "llvm/Support/MathExtras.h"
#include <cstdint>
+#include <memory>
using namespace lldb;
using namespace lldb_private;
@@ -62,10 +63,9 @@ void ValueObjectPrinter::Init(
m_summary.assign("");
m_error.assign("");
m_val_summary_ok = false;
- m_printed_instance_pointers =
- printed_instance_pointers
- ? printed_instance_pointers
- : InstancePointersSetSP(new InstancePointersSet());
+ m_printed_instance_pointers = printed_instance_pointers
+ ? printed_instance_pointers
+ : std::make_shared<InstancePointersSet>();
SetupMostSpecializedValue();
}
diff --git a/lldb/source/Host/common/FileSystem.cpp b/lldb/source/Host/common/FileSystem.cpp
index 5153a0a9..00919fe 100644
--- a/lldb/source/Host/common/FileSystem.cpp
+++ b/lldb/source/Host/common/FileSystem.cpp
@@ -35,6 +35,7 @@
#include <algorithm>
#include <fstream>
+#include <memory>
#include <optional>
#include <vector>
@@ -288,8 +289,7 @@ FileSystem::CreateWritableDataBuffer(const llvm::Twine &path, uint64_t size,
is_volatile);
if (!buffer)
return {};
- return std::shared_ptr<WritableDataBufferLLVM>(
- new WritableDataBufferLLVM(std::move(buffer)));
+ return std::make_shared<WritableDataBufferLLVM>(std::move(buffer));
}
std::shared_ptr<DataBuffer>
@@ -300,7 +300,7 @@ FileSystem::CreateDataBuffer(const llvm::Twine &path, uint64_t size,
GetMemoryBuffer<llvm::MemoryBuffer>(path, size, offset, is_volatile);
if (!buffer)
return {};
- return std::shared_ptr<DataBufferLLVM>(new DataBufferLLVM(std::move(buffer)));
+ return std::make_shared<DataBufferLLVM>(std::move(buffer));
}
std::shared_ptr<WritableDataBuffer>
diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp
index a1de895c..c0b1079 100644
--- a/lldb/source/Host/windows/MainLoopWindows.cpp
+++ b/lldb/source/Host/windows/MainLoopWindows.cpp
@@ -14,6 +14,7 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/Support/WindowsError.h"
#include <algorithm>
+#include <atomic>
#include <cassert>
#include <ctime>
#include <io.h>
@@ -222,7 +223,7 @@ MainLoopWindows::RegisterReadObject(const IOObjectSP &object_sp,
if (m_read_fds.find(waitable_handle) != m_read_fds.end()) {
error = Status::FromErrorStringWithFormat(
- "File descriptor %d already monitored.", waitable_handle);
+ "File descriptor %p already monitored.", waitable_handle);
return nullptr;
}
@@ -234,7 +235,7 @@ MainLoopWindows::RegisterReadObject(const IOObjectSP &object_sp,
} else {
DWORD file_type = GetFileType(waitable_handle);
if (file_type != FILE_TYPE_PIPE) {
- error = Status::FromErrorStringWithFormat("Unsupported file type %d",
+ error = Status::FromErrorStringWithFormat("Unsupported file type %ld",
file_type);
return nullptr;
}
diff --git a/lldb/source/Host/windows/PipeWindows.cpp b/lldb/source/Host/windows/PipeWindows.cpp
index 0b495ff..001396f 100644
--- a/lldb/source/Host/windows/PipeWindows.cpp
+++ b/lldb/source/Host/windows/PipeWindows.cpp
@@ -279,7 +279,8 @@ llvm::Expected<size_t> PipeWindows::Read(void *buf, size_t size,
return Status(failure_error, eErrorTypeWin32).takeError();
DWORD timeout_msec =
- timeout ? ceil<std::chrono::milliseconds>(*timeout).count() : INFINITE;
+ timeout ? std::chrono::ceil<std::chrono::milliseconds>(*timeout).count()
+ : INFINITE;
DWORD wait_result =
::WaitForSingleObject(m_read_overlapped.hEvent, timeout_msec);
if (wait_result != WAIT_OBJECT_0) {
@@ -324,7 +325,8 @@ llvm::Expected<size_t> PipeWindows::Write(const void *buf, size_t size,
return Status(failure_error, eErrorTypeWin32).takeError();
DWORD timeout_msec =
- timeout ? ceil<std::chrono::milliseconds>(*timeout).count() : INFINITE;
+ timeout ? std::chrono::ceil<std::chrono::milliseconds>(*timeout).count()
+ : INFINITE;
DWORD wait_result =
::WaitForSingleObject(m_write_overlapped.hEvent, timeout_msec);
if (wait_result != WAIT_OBJECT_0) {
diff --git a/lldb/source/Interpreter/CommandInterpreter.cpp b/lldb/source/Interpreter/CommandInterpreter.cpp
index da545f1..a0080cf 100644
--- a/lldb/source/Interpreter/CommandInterpreter.cpp
+++ b/lldb/source/Interpreter/CommandInterpreter.cpp
@@ -135,8 +135,7 @@ CommandInterpreter::CommandInterpreter(Debugger &debugger,
bool synchronous_execution)
: Broadcaster(debugger.GetBroadcasterManager(),
CommandInterpreter::GetStaticBroadcasterClass().str()),
- Properties(
- OptionValuePropertiesSP(new OptionValueProperties("interpreter"))),
+ Properties(std::make_shared<OptionValueProperties>("interpreter")),
IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand),
m_debugger(debugger), m_synchronous_execution(true),
m_skip_lldbinit_files(false), m_skip_app_init_files(false),
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp
index ae913e6..5ee19ff 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -116,6 +116,13 @@ lldb::StreamSP ScriptInterpreter::GetOpaqueTypeFromSBStream(
return nullptr;
}
+SymbolContext ScriptInterpreter::GetOpaqueTypeFromSBSymbolContext(
+ const lldb::SBSymbolContext &sb_sym_ctx) const {
+ if (sb_sym_ctx.m_opaque_up)
+ return *sb_sym_ctx.m_opaque_up.get();
+ return {};
+}
+
std::optional<MemoryRegionInfo>
ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo(
const lldb::SBMemoryRegionInfo &mem_region) const {
diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
index 6231f0f..47b137a 100644
--- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
+++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.h
@@ -225,7 +225,7 @@ public:
ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx);
if (context_md_iter == m_metadata_map.end()) {
- context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+ context_md = std::make_shared<ASTContextMetadata>(dst_ctx);
m_metadata_map[dst_ctx] = context_md;
} else {
context_md = context_md_iter->second;
@@ -438,7 +438,7 @@ public:
if (context_md_iter == m_metadata_map.end()) {
ASTContextMetadataSP context_md =
- ASTContextMetadataSP(new ASTContextMetadata(dst_ctx));
+ std::make_shared<ASTContextMetadata>(dst_ctx);
m_metadata_map[dst_ctx] = context_md;
return context_md;
}
@@ -462,7 +462,7 @@ public:
if (delegate_iter == delegates.end()) {
ImporterDelegateSP delegate =
- ImporterDelegateSP(new ASTImporterDelegate(*this, dst_ctx, src_ctx));
+ std::make_shared<ASTImporterDelegate>(*this, dst_ctx, src_ctx);
delegates[src_ctx] = delegate;
return delegate;
}
diff --git a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
index 7fe76a6..a5cee5d 100644
--- a/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
+++ b/lldb/source/Plugins/InstrumentationRuntime/Utility/Utility.cpp
@@ -23,10 +23,10 @@ lldb::ModuleSP GetPreferredAsanModule(const Target &target) {
target.GetImages().ForEach([&](const lldb::ModuleSP &m) {
if (pattern.match(m->GetFileSpec().GetFilename().GetStringRef())) {
module = m;
- return false;
+ return IterationAction::Stop;
}
- return true;
+ return IterationAction::Continue;
});
return module;
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
index ab9d991..cbc6f14 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
+++ b/lldb/source/Plugins/Language/CPlusPlus/CMakeLists.txt
@@ -35,7 +35,9 @@ add_lldb_library(lldbPluginCPlusPlusLanguage PLUGIN
LibStdcppUniquePointer.cpp
MsvcStl.cpp
MsvcStlAtomic.cpp
+ MsvcStlDeque.cpp
MsvcStlSmartPointer.cpp
+ MsvcStlTree.cpp
MsvcStlTuple.cpp
MsvcStlUnordered.cpp
MsvcStlVariant.cpp
diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
index 80dc460..46753c5 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp
@@ -1363,6 +1363,28 @@ static void RegisterStdStringSummaryProvider(
summary_sp);
}
+static void RegisterStdStringViewSummaryProvider(
+ const lldb::TypeCategoryImplSP &category_sp, llvm::StringRef string_ty,
+ llvm::StringRef char_ty, lldb::TypeSummaryImplSP summary_sp) {
+ // std::string_view
+ category_sp->AddTypeSummary(
+ std::make_shared<lldb_private::TypeNameSpecifierImpl>(
+ string_ty, eFormatterMatchExact),
+ summary_sp);
+
+ // std::basic_string_view<char, std::char_traits<char>>
+ // NativePDB has spaces at different positions compared to PDB and DWARF, so
+ // use a regex and make them optional.
+ category_sp->AddTypeSummary(
+ std::make_shared<lldb_private::TypeNameSpecifierImpl>(
+ llvm::formatv(
+ "^std::basic_string_view<{0}, ?std::char_traits<{0}> ?>$",
+ char_ty)
+ .str(),
+ eFormatterMatchRegex),
+ summary_sp);
+}
+
static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
return;
@@ -1409,27 +1431,27 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdVectorSynthProvider")));
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug::)?map<.+> >(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::map<.+> >(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_synth_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug)?deque<.+>(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::deque<.+>(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_deref_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider")));
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug::)?set<.+> >(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::set<.+> >(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_deref_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug::)?multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::multimap<.+> >(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_deref_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
cpp_category_sp->AddTypeSynthetic(
- "^std::(__debug::)?multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
+ "^std::__debug::multiset<.+> >(( )?&)?$", eFormatterMatchRegex,
SyntheticChildrenSP(new ScriptedSyntheticChildren(
stl_deref_flags,
"lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider")));
@@ -1462,30 +1484,29 @@ static void LoadLibStdcppFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"libstdc++ std::__debug::vector summary provider",
"^std::__debug::vector<.+>(( )?&)?$", stl_summary_flags, true);
- AddCXXSummary(
- cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::map summary provider",
- "^std::(__debug::)?map<.+> >(( )?&)?$", stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::ContainerSizeSummaryProvider,
+ "libstdc++ debug std::map summary provider",
+ "^std::__debug::map<.+> >(( )?&)?$", stl_summary_flags, true);
- AddCXXSummary(
- cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::set summary provider",
- "^std::(__debug::)?set<.+> >(( )?&)?$", stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp,
+ lldb_private::formatters::ContainerSizeSummaryProvider,
+ "libstdc++ debug std::set summary provider",
+ "^std::__debug::set<.+> >(( )?&)?$", stl_summary_flags, true);
- AddCXXSummary(
- cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::deque summary provider",
- "^std::(__debug::)?deque<.+>(( )?&)?$", stl_summary_flags, true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "libstdc++ debug std::deque summary provider",
+ "^std::__debug::deque<.+>(( )?&)?$", stl_summary_flags, true);
AddCXXSummary(
cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::multimap summary provider",
- "^std::(__debug::)?multimap<.+> >(( )?&)?$", stl_summary_flags, true);
+ "libstdc++ debug std::multimap summary provider",
+ "^std::__debug::multimap<.+> >(( )?&)?$", stl_summary_flags, true);
AddCXXSummary(
cpp_category_sp, lldb_private::formatters::ContainerSizeSummaryProvider,
- "libstdc++ std::multiset summary provider",
- "^std::(__debug::)?multiset<.+> >(( )?&)?$", stl_summary_flags, true);
+ "libstdc++ debug std::multiset summary provider",
+ "^std::__debug::multiset<.+> >(( )?&)?$", stl_summary_flags, true);
AddCXXSummary(cpp_category_sp,
lldb_private::formatters::ContainerSizeSummaryProvider,
@@ -1672,6 +1693,30 @@ GenericUnorderedSyntheticFrontEndCreator(CXXSyntheticChildren *children,
*valobj_sp);
}
+static SyntheticChildrenFrontEnd *
+GenericMapLikeSyntheticFrontEndCreator(CXXSyntheticChildren *children,
+ ValueObjectSP valobj_sp) {
+ if (!valobj_sp)
+ return nullptr;
+
+ if (IsMsvcStlMapLike(*valobj_sp))
+ return MsvcStlMapLikeSyntheticFrontEndCreator(valobj_sp);
+ return new ScriptedSyntheticChildren::FrontEnd(
+ "lldb.formatters.cpp.gnu_libstdcpp.StdMapLikeSynthProvider", *valobj_sp);
+}
+
+static SyntheticChildrenFrontEnd *
+GenericDequeSyntheticFrontEndCreator(CXXSyntheticChildren *children,
+ ValueObjectSP valobj_sp) {
+ if (!valobj_sp)
+ return nullptr;
+
+ if (IsMsvcStlDeque(*valobj_sp))
+ return MsvcStlDequeSyntheticFrontEndCreator(children, valobj_sp);
+ return new ScriptedSyntheticChildren::FrontEnd(
+ "lldb.formatters.cpp.gnu_libstdcpp.StdDequeSynthProvider", *valobj_sp);
+}
+
/// Load formatters that are formatting types from more than one STL
static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
if (!cpp_category_sp)
@@ -1749,6 +1794,14 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
AddCXXSynthetic(cpp_category_sp, GenericOptionalSyntheticFrontEndCreator,
"std::optional synthetic children",
"^std::optional<.+>(( )?&)?$", stl_deref_flags, true);
+ AddCXXSynthetic(cpp_category_sp, GenericDequeSyntheticFrontEndCreator,
+ "std::deque container synthetic children",
+ "^std::deque<.+>(( )?&)?$", stl_deref_flags, true);
+
+ AddCXXSynthetic(cpp_category_sp, GenericMapLikeSyntheticFrontEndCreator,
+ "std::(multi)?map/set synthetic children",
+ "^std::(multi)?(map|set)<.+>(( )?&)?$", stl_synth_flags,
+ true);
AddCXXSummary(cpp_category_sp, GenericSmartPointerSummaryProvider,
"MSVC STL/libstdc++ std::shared_ptr summary provider",
@@ -1786,6 +1839,13 @@ static void LoadCommonStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
"MSVC STL/libstdc++ std unordered container summary provider",
"^std::unordered_(multi)?(map|set)<.+> ?>$", stl_summary_flags,
true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "MSVC STL/libstdc++ std::(multi)?map/set summary provider",
+ "^std::(multi)?(map|set)<.+>(( )?&)?$", stl_summary_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, ContainerSizeSummaryProvider,
+ "MSVC STL/libstd++ std::deque summary provider",
+ "^std::deque<.+>(( )?&)?$", stl_summary_flags, true);
}
static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
@@ -1825,6 +1885,36 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
MsvcStlStringSummaryProvider<StringElementType::UTF32>,
"MSVC STL std::u32string summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::string_view", "char",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ MsvcStlStringViewSummaryProvider<StringElementType::ASCII>,
+ "MSVC STL std::string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u8string_view", "char8_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ MsvcStlStringViewSummaryProvider<StringElementType::UTF8>,
+ "MSVC STL std::u8string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u16string_view", "char16_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ MsvcStlStringViewSummaryProvider<StringElementType::UTF16>,
+ "MSVC STL std::u16string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::u32string_view", "char32_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags,
+ MsvcStlStringViewSummaryProvider<StringElementType::UTF32>,
+ "MSVC STL std::u32string_view summary provider"));
+ RegisterStdStringViewSummaryProvider(
+ cpp_category_sp, "std::wstring_view", "wchar_t",
+ std::make_shared<CXXFunctionSummaryFormat>(
+ stl_summary_flags, MsvcStlWStringViewSummaryProvider,
+ "MSVC STL std::wstring_view summary provider"));
+
stl_summary_flags.SetDontShowChildren(false);
AddCXXSynthetic(cpp_category_sp, MsvcStlAtomicSyntheticFrontEndCreator,
@@ -1834,6 +1924,14 @@ static void LoadMsvcStlFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
AddCXXSummary(cpp_category_sp, MsvcStlAtomicSummaryProvider,
"MSVC STL std::atomic summary provider", "^std::atomic<.+>$",
stl_summary_flags, true);
+ AddCXXSynthetic(cpp_category_sp, MsvcStlTreeIterSyntheticFrontEndCreator,
+ "MSVC STL tree iterator synthetic children",
+ "^std::_Tree(_const)?_iterator<.+>(( )?&)?$", stl_synth_flags,
+ true);
+ AddCXXSummary(cpp_category_sp, MsvcStlTreeIterSummaryProvider,
+ "MSVC STL tree iterator summary",
+ "^std::_Tree(_const)?_iterator<.+>(( )?&)?$", stl_summary_flags,
+ true);
}
static void LoadSystemFormatters(lldb::TypeCategoryImplSP cpp_category_sp) {
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
index 5d0f20b..8fb305b 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.cpp
@@ -112,6 +112,33 @@ static bool formatStringImpl(ValueObject &valobj, Stream &stream,
return true;
}
+template <StringPrinter::StringElementType element_type>
+static bool formatStringViewImpl(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options,
+ std::string prefix_token) {
+ auto data_sp = valobj.GetChildMemberWithName("_Mydata");
+ auto size_sp = valobj.GetChildMemberWithName("_Mysize");
+ if (!data_sp || !size_sp)
+ return false;
+
+ bool success = false;
+ uint64_t size = size_sp->GetValueAsUnsigned(0, &success);
+ if (!success) {
+ stream << "Summary Unavailable";
+ return true;
+ }
+
+ StreamString scratch_stream;
+ success = StringBufferSummaryProvider<element_type>(
+ scratch_stream, summary_options, data_sp, size, prefix_token);
+
+ if (success)
+ stream << scratch_stream.GetData();
+ else
+ stream << "Summary Unavailable";
+ return true;
+}
+
bool lldb_private::formatters::IsMsvcStlStringType(ValueObject &valobj) {
std::vector<uint32_t> indexes;
return valobj.GetCompilerType().GetIndexOfChildMemberWithName("_Mypair", true,
@@ -153,3 +180,39 @@ bool lldb_private::formatters::MsvcStlStringSummaryProvider<
return MsvcStlStringSummaryProviderImpl<StringElementType::UTF32>(
valobj, stream, summary_options, "U");
}
+
+bool lldb_private::formatters::MsvcStlWStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return formatStringViewImpl<StringElementType::UTF16>(valobj, stream,
+ summary_options, "L");
+}
+
+template <>
+bool lldb_private::formatters::MsvcStlStringViewSummaryProvider<
+ StringElementType::ASCII>(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return formatStringViewImpl<StringElementType::ASCII>(valobj, stream,
+ summary_options, "");
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringViewSummaryProvider<
+ StringElementType::UTF8>(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return formatStringViewImpl<StringElementType::UTF8>(valobj, stream,
+ summary_options, "u8");
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringViewSummaryProvider<
+ StringElementType::UTF16>(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return formatStringViewImpl<StringElementType::UTF16>(valobj, stream,
+ summary_options, "u");
+}
+template <>
+bool lldb_private::formatters::MsvcStlStringViewSummaryProvider<
+ StringElementType::UTF32>(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options) {
+ return formatStringViewImpl<StringElementType::UTF32>(valobj, stream,
+ summary_options, "U");
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
index e2a015a..8a49181 100644
--- a/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStl.h
@@ -29,6 +29,15 @@ bool MsvcStlWStringSummaryProvider(
ValueObject &valobj, Stream &stream,
const TypeSummaryOptions &options); // VC 2015+ std::wstring
+template <StringPrinter::StringElementType element_type>
+bool MsvcStlStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &summary_options); // std::{u8,u16,u32}?string_view
+
+bool MsvcStlWStringViewSummaryProvider(
+ ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options); // std::wstring_view
+
// MSVC STL std::shared_ptr<> and std::weak_ptr<>
bool IsMsvcStlSmartPointer(ValueObject &valobj);
bool MsvcStlSmartPointerSummaryProvider(ValueObject &valobj, Stream &stream,
@@ -91,6 +100,23 @@ bool IsMsvcStlUnordered(ValueObject &valobj);
SyntheticChildrenFrontEnd *
MsvcStlUnorderedSyntheticFrontEndCreator(CXXSyntheticChildren *,
lldb::ValueObjectSP valobj_sp);
+bool IsMsvcStlTreeIter(ValueObject &valobj);
+bool MsvcStlTreeIterSummaryProvider(ValueObject &valobj, Stream &stream,
+ const TypeSummaryOptions &options);
+lldb_private::SyntheticChildrenFrontEnd *
+MsvcStlTreeIterSyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
+
+// std::map,set,multimap,multiset
+bool IsMsvcStlMapLike(ValueObject &valobj);
+lldb_private::SyntheticChildrenFrontEnd *
+MsvcStlMapLikeSyntheticFrontEndCreator(lldb::ValueObjectSP valobj_sp);
+
+// MSVC STL std::deque<>
+bool IsMsvcStlDeque(ValueObject &valobj);
+SyntheticChildrenFrontEnd *
+MsvcStlDequeSyntheticFrontEndCreator(CXXSyntheticChildren *,
+ lldb::ValueObjectSP valobj_sp);
} // namespace formatters
} // namespace lldb_private
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp
new file mode 100644
index 0000000..8733543
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlDeque.cpp
@@ -0,0 +1,174 @@
+//===-- MsvcStlDeque.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 "MsvcStl.h"
+
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/DataFormatters/TypeSynthetic.h"
+
+using namespace lldb;
+
+namespace lldb_private {
+namespace formatters {
+
+class MsvcStlDequeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ MsvcStlDequeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+ lldb::ChildCacheState Update() override;
+
+ llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ ValueObject *m_map = nullptr;
+ ExecutionContextRef m_exe_ctx_ref;
+
+ size_t m_block_size = 0;
+ size_t m_offset = 0;
+ size_t m_map_size = 0;
+
+ size_t m_element_size = 0;
+ CompilerType m_element_type;
+
+ uint32_t m_size = 0;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::
+ MsvcStlDequeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
+ if (valobj_sp)
+ Update();
+}
+
+llvm::Expected<uint32_t> lldb_private::formatters::
+ MsvcStlDequeSyntheticFrontEnd::CalculateNumChildren() {
+ if (!m_map)
+ return llvm::createStringError("Failed to read size");
+ return m_size;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::GetChildAtIndex(
+ uint32_t idx) {
+ if (idx >= m_size || !m_map)
+ return nullptr;
+ ProcessSP process_sp(m_exe_ctx_ref.GetProcessSP());
+ if (!process_sp)
+ return nullptr;
+
+ // _EEN_DS = _Block_size
+ // _Map[(($i + _Myoff) / _EEN_DS) % _Mapsize][($i + _Myoff) % _EEN_DS]
+ size_t first_idx = ((idx + m_offset) / m_block_size) % m_map_size;
+ lldb::addr_t first_address = m_map->GetValueAsUnsigned(0) +
+ first_idx * process_sp->GetAddressByteSize();
+
+ Status err;
+ lldb::addr_t second_base =
+ process_sp->ReadPointerFromMemory(first_address, err);
+ if (err.Fail())
+ return nullptr;
+
+ size_t second_idx = (idx + m_offset) % m_block_size;
+ size_t second_address = second_base + second_idx * m_element_size;
+
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return CreateValueObjectFromAddress(name.GetString(), second_address,
+ m_backend.GetExecutionContextRef(),
+ m_element_type);
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::Update() {
+ m_size = 0;
+ m_map = nullptr;
+ m_element_type.Clear();
+
+ auto storage_sp = m_backend.GetChildAtNamePath({"_Mypair", "_Myval2"});
+ if (!storage_sp)
+ return lldb::eRefetch;
+
+ auto deque_type = m_backend.GetCompilerType();
+ if (!deque_type)
+ return lldb::eRefetch;
+
+ auto block_size_decl = deque_type.GetStaticFieldWithName("_Block_size");
+ if (!block_size_decl)
+ return lldb::eRefetch;
+ auto block_size = block_size_decl.GetConstantValue();
+ if (!block_size.IsValid())
+ return lldb::eRefetch;
+
+ auto element_type = deque_type.GetTypeTemplateArgument(0);
+ if (!element_type)
+ return lldb::eRefetch;
+ auto element_size = element_type.GetByteSize(nullptr);
+ if (!element_size)
+ return lldb::eRefetch;
+
+ auto offset_sp = storage_sp->GetChildMemberWithName("_Myoff");
+ auto map_size_sp = storage_sp->GetChildMemberWithName("_Mapsize");
+ auto map_sp = storage_sp->GetChildMemberWithName("_Map");
+ auto size_sp = storage_sp->GetChildMemberWithName("_Mysize");
+ if (!offset_sp || !map_size_sp || !map_sp || !size_sp)
+ return lldb::eRefetch;
+
+ bool ok = false;
+ uint64_t offset = offset_sp->GetValueAsUnsigned(0, &ok);
+ if (!ok)
+ return lldb::eRefetch;
+
+ uint64_t map_size = map_size_sp->GetValueAsUnsigned(0, &ok);
+ if (!ok)
+ return lldb::eRefetch;
+
+ uint64_t size = size_sp->GetValueAsUnsigned(0, &ok);
+ if (!ok)
+ return lldb::eRefetch;
+
+ m_map = map_sp.get();
+ m_exe_ctx_ref = m_backend.GetExecutionContextRef();
+ m_block_size = block_size.ULongLong();
+ m_offset = offset;
+ m_map_size = map_size;
+ m_element_size = *element_size;
+ m_element_type = element_type;
+ m_size = size;
+ return lldb::eRefetch;
+}
+
+llvm::Expected<size_t> lldb_private::formatters::MsvcStlDequeSyntheticFrontEnd::
+ GetIndexOfChildWithName(ConstString name) {
+ if (!m_map)
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ if (auto optional_idx = ExtractIndexFromString(name.GetCString()))
+ return *optional_idx;
+
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+}
+
+bool lldb_private::formatters::IsMsvcStlDeque(ValueObject &valobj) {
+ if (auto valobj_sp = valobj.GetNonSyntheticValue())
+ return valobj_sp->GetChildMemberWithName("_Mypair") != nullptr;
+ return false;
+}
+
+lldb_private::SyntheticChildrenFrontEnd *
+lldb_private::formatters::MsvcStlDequeSyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+ return new MsvcStlDequeSyntheticFrontEnd(valobj_sp);
+}
diff --git a/lldb/source/Plugins/Language/CPlusPlus/MsvcStlTree.cpp b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlTree.cpp
new file mode 100644
index 0000000..ddf6c27
--- /dev/null
+++ b/lldb/source/Plugins/Language/CPlusPlus/MsvcStlTree.cpp
@@ -0,0 +1,407 @@
+//===-- MsvcStlTree.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 "MsvcStl.h"
+
+#include "lldb/DataFormatters/FormattersHelpers.h"
+#include "lldb/Utility/Status.h"
+#include "lldb/ValueObject/ValueObject.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-forward.h"
+#include <cstdint>
+#include <optional>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::formatters;
+
+// A Node looks as follows:
+// struct _Tree_node {
+// _Tree_node *_Left;
+// _Tree_node *_Parent;
+// _Tree_node *_Right;
+// char _Color;
+// char _Isnil; // true (!= 0) if head or nil node
+// value_type _Myval;
+// };
+
+namespace {
+
+class MapEntry {
+public:
+ MapEntry() = default;
+ explicit MapEntry(ValueObjectSP entry_sp) : m_entry_sp(entry_sp) {}
+ explicit MapEntry(ValueObject *entry)
+ : m_entry_sp(entry ? entry->GetSP() : ValueObjectSP()) {}
+
+ ValueObjectSP left() const {
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetSyntheticChildAtOffset(
+ 0, m_entry_sp->GetCompilerType(), true);
+ }
+
+ ValueObjectSP right() const {
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetSyntheticChildAtOffset(
+ 2 * m_entry_sp->GetProcessSP()->GetAddressByteSize(),
+ m_entry_sp->GetCompilerType(), true);
+ }
+
+ ValueObjectSP parent() const {
+ if (!m_entry_sp)
+ return m_entry_sp;
+ return m_entry_sp->GetSyntheticChildAtOffset(
+ m_entry_sp->GetProcessSP()->GetAddressByteSize(),
+ m_entry_sp->GetCompilerType(), true);
+ }
+
+ uint64_t value() const {
+ if (!m_entry_sp)
+ return 0;
+ return m_entry_sp->GetValueAsUnsigned(0);
+ }
+
+ bool is_nil() const {
+ if (!m_entry_sp)
+ return true;
+ auto isnil_sp = m_entry_sp->GetChildMemberWithName("_Isnil");
+ if (!isnil_sp)
+ return true;
+ return isnil_sp->GetValueAsUnsigned(1) != 0;
+ }
+
+ bool error() const {
+ if (!m_entry_sp)
+ return true;
+ return m_entry_sp->GetError().Fail();
+ }
+
+ bool is_nullptr() const { return (value() == 0); }
+
+ ValueObjectSP GetEntry() const { return m_entry_sp; }
+
+ void SetEntry(ValueObjectSP entry) { m_entry_sp = entry; }
+
+ bool operator==(const MapEntry &rhs) const {
+ return (rhs.m_entry_sp.get() == m_entry_sp.get());
+ }
+
+private:
+ ValueObjectSP m_entry_sp;
+};
+
+class MapIterator {
+public:
+ MapIterator(ValueObject *entry, size_t depth = 0)
+ : m_entry(entry), m_max_depth(depth) {}
+
+ MapIterator() = default;
+
+ ValueObjectSP value() { return m_entry.GetEntry(); }
+
+ ValueObjectSP advance(size_t count) {
+ ValueObjectSP fail;
+ if (m_error)
+ return fail;
+ size_t steps = 0;
+ while (count > 0) {
+ next();
+ count--, steps++;
+ if (m_error || m_entry.is_nullptr() || (steps > m_max_depth))
+ return fail;
+ }
+ return m_entry.GetEntry();
+ }
+
+private:
+ /// Mimicks _Tree_unchecked_const_iterator::operator++()
+ void next() {
+ if (m_entry.is_nullptr())
+ return;
+ MapEntry right(m_entry.right());
+ if (!right.is_nil()) {
+ m_entry = tree_min(std::move(right));
+ return;
+ }
+ size_t steps = 0;
+ MapEntry pnode(m_entry.parent());
+ while (!pnode.is_nil() &&
+ m_entry.value() == MapEntry(pnode.right()).value()) {
+ m_entry = pnode;
+ steps++;
+ if (steps > m_max_depth) {
+ m_entry = MapEntry();
+ return;
+ }
+ pnode.SetEntry(m_entry.parent());
+ }
+ m_entry = std::move(pnode);
+ }
+
+ /// Mimicks MSVC STL's _Min() algorithm (finding the leftmost node in the
+ /// subtree).
+ MapEntry tree_min(MapEntry pnode) {
+ if (pnode.is_nullptr())
+ return MapEntry();
+ MapEntry left(pnode.left());
+ size_t steps = 0;
+ while (!left.is_nil()) {
+ if (left.error()) {
+ m_error = true;
+ return MapEntry();
+ }
+ pnode = left;
+ left.SetEntry(pnode.left());
+ steps++;
+ if (steps > m_max_depth)
+ return MapEntry();
+ }
+ return pnode;
+ }
+
+ MapEntry m_entry;
+ size_t m_max_depth = 0;
+ bool m_error = false;
+};
+
+} // namespace
+
+namespace lldb_private {
+namespace formatters {
+class MsvcStlTreeSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ MsvcStlTreeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp);
+
+ ~MsvcStlTreeSyntheticFrontEnd() override = default;
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override;
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override;
+
+ lldb::ChildCacheState Update() override;
+
+ llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override;
+
+private:
+ /// Returns the ValueObject for the _Tree_node at index \ref idx.
+ ///
+ /// \param[in] idx The child index that we're looking to get the value for.
+ ///
+ /// \param[in] max_depth The maximum search depth after which we stop trying
+ /// to find the node for.
+ ///
+ /// \returns On success, returns the ValueObjectSP corresponding to the
+ /// _Tree_node's _Myval member.
+ /// On failure, nullptr is returned.
+ ValueObjectSP GetValueAt(size_t idx, size_t max_depth);
+
+ ValueObject *m_tree = nullptr;
+ ValueObject *m_begin_node = nullptr;
+ size_t m_count = UINT32_MAX;
+ std::map<size_t, MapIterator> m_iterators;
+};
+
+class MsvcStlTreeIterSyntheticFrontEnd : public SyntheticChildrenFrontEnd {
+public:
+ MsvcStlTreeIterSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp) {}
+
+ llvm::Expected<uint32_t> CalculateNumChildren() override {
+ if (!m_inner_sp)
+ return 0;
+ return m_inner_sp->GetNumChildren();
+ }
+
+ lldb::ValueObjectSP GetChildAtIndex(uint32_t idx) override {
+ if (!m_inner_sp)
+ return nullptr;
+ return m_inner_sp->GetChildAtIndex(idx);
+ }
+
+ lldb::ChildCacheState Update() override;
+
+ llvm::Expected<size_t> GetIndexOfChildWithName(ConstString name) override {
+ if (!m_inner_sp)
+ return llvm::createStringError("There are no children.");
+ return m_inner_sp->GetIndexOfChildWithName(name);
+ }
+
+ lldb::ValueObjectSP GetSyntheticValue() override { return m_inner_sp; }
+
+private:
+ ValueObjectSP m_inner_sp;
+};
+
+} // namespace formatters
+} // namespace lldb_private
+
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::
+ MsvcStlTreeSyntheticFrontEnd(lldb::ValueObjectSP valobj_sp)
+ : SyntheticChildrenFrontEnd(*valobj_sp) {
+ if (valobj_sp)
+ Update();
+}
+
+llvm::Expected<uint32_t>
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::CalculateNumChildren() {
+ if (m_count != UINT32_MAX)
+ return m_count;
+
+ if (m_tree == nullptr)
+ return 0;
+
+ if (auto node_sp = m_tree->GetChildMemberWithName("_Mysize")) {
+ m_count = node_sp->GetValueAsUnsigned(0);
+ return m_count;
+ }
+
+ return llvm::createStringError("Failed to read size.");
+}
+
+ValueObjectSP
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::GetValueAt(
+ size_t idx, size_t max_depth) {
+ MapIterator iterator(m_begin_node, max_depth);
+
+ size_t advance_by = idx;
+ if (idx > 0) {
+ // If we have already created the iterator for the previous
+ // index, we can start from there and advance by 1.
+ auto cached_iterator = m_iterators.find(idx - 1);
+ if (cached_iterator != m_iterators.end()) {
+ iterator = cached_iterator->second;
+ advance_by = 1;
+ }
+ }
+
+ ValueObjectSP iterated_sp(iterator.advance(advance_by));
+ if (!iterated_sp)
+ // this tree is garbage - stop
+ return nullptr;
+
+ ValueObjectSP value_sp = iterated_sp->GetChildMemberWithName("_Myval");
+ if (!value_sp)
+ return nullptr;
+
+ m_iterators[idx] = iterator;
+
+ return value_sp;
+}
+
+lldb::ValueObjectSP
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::GetChildAtIndex(
+ uint32_t idx) {
+ uint32_t num_children = CalculateNumChildrenIgnoringErrors();
+ if (idx >= num_children)
+ return nullptr;
+
+ if (m_tree == nullptr || m_begin_node == nullptr)
+ return nullptr;
+
+ ValueObjectSP val_sp = GetValueAt(idx, /*max_depth=*/num_children);
+ if (!val_sp) {
+ // this will stop all future searches until an Update() happens
+ m_tree = nullptr;
+ return nullptr;
+ }
+
+ // at this point we have a valid pair
+ // we need to copy current_sp into a new object otherwise we will end up with
+ // all items named _Myval
+ StreamString name;
+ name.Printf("[%" PRIu64 "]", (uint64_t)idx);
+ return val_sp->Clone(ConstString(name.GetString()));
+}
+
+lldb::ChildCacheState
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::Update() {
+ m_count = UINT32_MAX;
+ m_tree = m_begin_node = nullptr;
+ m_iterators.clear();
+ m_tree =
+ m_backend.GetChildAtNamePath({"_Mypair", "_Myval2", "_Myval2"}).get();
+ if (!m_tree)
+ return lldb::ChildCacheState::eRefetch;
+
+ m_begin_node = m_tree->GetChildAtNamePath({"_Myhead", "_Left"}).get();
+
+ return lldb::ChildCacheState::eRefetch;
+}
+
+llvm::Expected<size_t>
+lldb_private::formatters::MsvcStlTreeSyntheticFrontEnd::GetIndexOfChildWithName(
+ ConstString name) {
+ auto optional_idx = formatters::ExtractIndexFromString(name.GetCString());
+ if (!optional_idx) {
+ return llvm::createStringError("Type has no child named '%s'",
+ name.AsCString());
+ }
+ return *optional_idx;
+}
+
+lldb::ChildCacheState MsvcStlTreeIterSyntheticFrontEnd::Update() {
+ m_inner_sp = nullptr;
+ auto node_sp = m_backend.GetChildMemberWithName("_Ptr");
+ if (!node_sp)
+ return lldb::eRefetch;
+
+ MapEntry entry(node_sp.get());
+ if (entry.is_nil())
+ return lldb::eRefetch; // end
+
+ m_inner_sp = node_sp->GetChildMemberWithName("_Myval");
+ return lldb::eRefetch;
+}
+
+bool formatters::IsMsvcStlTreeIter(ValueObject &valobj) {
+ return valobj.GetChildMemberWithName("_Ptr") != nullptr;
+}
+
+bool formatters::MsvcStlTreeIterSummaryProvider(
+ ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) {
+ auto valobj_sp = valobj.GetNonSyntheticValue();
+ if (!valobj_sp)
+ return false;
+ auto node_sp = valobj_sp->GetChildMemberWithName("_Ptr");
+ if (!node_sp)
+ return false;
+
+ MapEntry entry(node_sp.get());
+ if (entry.is_nil()) {
+ stream.Printf("end");
+ return true;
+ }
+
+ auto value_sp = node_sp->GetChildMemberWithName("_Myval");
+ if (!value_sp)
+ return false;
+
+ auto *summary = value_sp->GetSummaryAsCString();
+ if (summary)
+ stream << summary;
+ return true;
+}
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::MsvcStlTreeIterSyntheticFrontEndCreator(
+ CXXSyntheticChildren *, lldb::ValueObjectSP valobj_sp) {
+ return (valobj_sp ? new MsvcStlTreeIterSyntheticFrontEnd(valobj_sp)
+ : nullptr);
+}
+
+bool formatters::IsMsvcStlMapLike(ValueObject &valobj) {
+ return valobj.GetChildMemberWithName("_Mypair") != nullptr;
+}
+
+SyntheticChildrenFrontEnd *
+lldb_private::formatters::MsvcStlMapLikeSyntheticFrontEndCreator(
+ lldb::ValueObjectSP valobj_sp) {
+ return (valobj_sp ? new MsvcStlTreeSyntheticFrontEnd(valobj_sp) : nullptr);
+}
diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
index 4fcdebe..cca721e 100644
--- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
+++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp
@@ -3462,7 +3462,7 @@ public:
*exception, eValueTypeVariableArgument);
exception = exception->GetDynamicValue(eDynamicDontRunTarget);
- m_arguments = ValueObjectListSP(new ValueObjectList());
+ m_arguments = std::make_shared<ValueObjectList>();
m_arguments->Append(exception);
m_stop_desc = "hit Objective-C exception";
diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
index fe28213..25e9888 100644
--- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
+++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp
@@ -201,7 +201,7 @@ Status MinidumpFileBuilder::AddSystemInfo() {
return error;
};
- llvm::minidump::SystemInfo sys_info;
+ llvm::minidump::SystemInfo sys_info{};
sys_info.ProcessorArch =
static_cast<llvm::support::little_t<ProcessorArchitecture>>(arch);
// Global offset to beginning of a csd_string in a data section
@@ -378,7 +378,7 @@ Status MinidumpFileBuilder::AddModuleList() {
helper_data.AppendData(&signature, sizeof(llvm::support::ulittle32_t));
helper_data.AppendData(uuid.begin(), uuid.size());
- llvm::minidump::Module m;
+ llvm::minidump::Module m{};
m.BaseOfImage = static_cast<llvm::support::ulittle64_t>(
mod->GetObjectFile()->GetBaseAddress().GetLoadAddress(&target));
m.SizeOfImage = static_cast<llvm::support::ulittle32_t>(mod_size);
@@ -745,7 +745,7 @@ lldb_private::Status MinidumpFileBuilder::AddMiscInfo() {
if (error.Fail())
return error;
- lldb_private::minidump::MinidumpMiscInfo misc_info;
+ lldb_private::minidump::MinidumpMiscInfo misc_info{};
misc_info.size = static_cast<llvm::support::ulittle32_t>(
sizeof(lldb_private::minidump::MinidumpMiscInfo));
// Default set flags1 to 0, in case that we will not be able to
diff --git a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
index 54869001..07c5a52 100644
--- a/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
+++ b/lldb/source/Plugins/Platform/MacOSX/PlatformDarwinKernel.cpp
@@ -805,7 +805,7 @@ Status PlatformDarwinKernel::GetSharedModuleKernel(
if (FileSystem::Instance().Exists(possible_kernel)) {
ModuleSpec kern_spec(possible_kernel);
kern_spec.GetUUID() = module_spec.GetUUID();
- module_sp.reset(new Module(kern_spec));
+ module_sp = std::make_shared<Module>(kern_spec);
if (module_sp && module_sp->GetObjectFile() &&
module_sp->MatchesModuleSpec(kern_spec)) {
// The dSYM is next to the binary (that's the only
@@ -835,7 +835,7 @@ Status PlatformDarwinKernel::GetSharedModuleKernel(
kern_spec.GetUUID() = module_spec.GetUUID();
kern_spec.GetSymbolFileSpec() = possible_kernel_dsym;
- module_sp.reset(new Module(kern_spec));
+ module_sp = std::make_shared<Module>(kern_spec);
if (module_sp && module_sp->GetObjectFile() &&
module_sp->MatchesModuleSpec(kern_spec)) {
if (did_create_ptr)
diff --git a/lldb/source/Plugins/Process/CMakeLists.txt b/lldb/source/Plugins/Process/CMakeLists.txt
index bd9b1b8..3413360 100644
--- a/lldb/source/Plugins/Process/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/CMakeLists.txt
@@ -29,3 +29,4 @@ add_subdirectory(elf-core)
add_subdirectory(mach-core)
add_subdirectory(minidump)
add_subdirectory(FreeBSDKernel)
+add_subdirectory(wasm)
diff --git a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
index 7adc006..d21dac2 100644
--- a/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/NativeRegisterContextFreeBSD_arm64.cpp
@@ -44,7 +44,8 @@ NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
NativeProcessFreeBSD &process = native_thread.GetProcess();
g_register_flags_detector.DetectFields(
process.GetAuxValue(AuxVector::AUXV_FREEBSD_AT_HWCAP).value_or(0),
- process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0));
+ process.GetAuxValue(AuxVector::AUXV_AT_HWCAP2).value_or(0),
+ /*hwcap3=*/0);
}
return new NativeRegisterContextFreeBSD_arm64(target_arch, native_thread);
diff --git a/lldb/source/Plugins/Process/Linux/CMakeLists.txt b/lldb/source/Plugins/Process/Linux/CMakeLists.txt
index 33af2e2..bb69016 100644
--- a/lldb/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Linux/CMakeLists.txt
@@ -8,6 +8,7 @@ add_lldb_library(lldbPluginProcessLinux
NativeRegisterContextLinux.cpp
NativeRegisterContextLinux_arm.cpp
NativeRegisterContextLinux_arm64.cpp
+ NativeRegisterContextLinux_arm64dbreg.cpp
NativeRegisterContextLinux_loongarch64.cpp
NativeRegisterContextLinux_ppc64le.cpp
NativeRegisterContextLinux_riscv64.cpp
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
index dc7fb10..fdafacf 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.cpp
@@ -23,13 +23,19 @@
#include <elf.h>
#include <sys/uio.h>
+#if defined(__arm64__) || defined(__aarch64__)
+#include "NativeRegisterContextLinux_arm64dbreg.h"
+#include "lldb/Host/linux/Ptrace.h"
+#include <asm/ptrace.h>
+#endif
+
#define REG_CONTEXT_SIZE (GetGPRSize() + sizeof(m_fpr))
#ifndef PTRACE_GETVFPREGS
#define PTRACE_GETVFPREGS 27
#define PTRACE_SETVFPREGS 28
#endif
-#ifndef PTRACE_GETHBPREGS
+#if defined(__arm__) && !defined(PTRACE_GETHBPREGS)
#define PTRACE_GETHBPREGS 29
#define PTRACE_SETHBPREGS 30
#endif
@@ -342,7 +348,8 @@ NativeRegisterContextLinux_arm::SetHardwareBreakpoint(lldb::addr_t addr,
m_hbr_regs[bp_index].control = control_value;
// PTRACE call to set corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK, bp_index);
+ error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK,
+ bp_index);
if (error.Fail()) {
m_hbr_regs[bp_index].address = 0;
@@ -375,7 +382,8 @@ bool NativeRegisterContextLinux_arm::ClearHardwareBreakpoint(uint32_t hw_idx) {
m_hbr_regs[hw_idx].address = 0;
// PTRACE call to clear corresponding hardware breakpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeBREAK, hw_idx);
+ error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK,
+ hw_idx);
if (error.Fail()) {
m_hbr_regs[hw_idx].control = tempControl;
@@ -435,7 +443,8 @@ Status NativeRegisterContextLinux_arm::ClearAllHardwareBreakpoints() {
m_hbr_regs[i].address = 0;
// Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeBREAK, i);
+ error =
+ WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeBREAK, i);
if (error.Fail()) {
m_hbr_regs[i].control = tempControl;
@@ -555,7 +564,8 @@ uint32_t NativeRegisterContextLinux_arm::SetHardwareWatchpoint(
m_hwp_regs[wp_index].control = control_value;
// PTRACE call to set corresponding watchpoint register.
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
+ error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH,
+ wp_index);
if (error.Fail()) {
m_hwp_regs[wp_index].address = 0;
@@ -590,7 +600,8 @@ bool NativeRegisterContextLinux_arm::ClearHardwareWatchpoint(
m_hwp_regs[wp_index].address = 0;
// Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, wp_index);
+ error = WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH,
+ wp_index);
if (error.Fail()) {
m_hwp_regs[wp_index].control = tempControl;
@@ -623,7 +634,8 @@ Status NativeRegisterContextLinux_arm::ClearAllHardwareWatchpoints() {
m_hwp_regs[i].address = 0;
// Ptrace call to update hardware debug registers
- error = WriteHardwareDebugRegs(eDREGTypeWATCH, i);
+ error =
+ WriteHardwareDebugRegs(NativeRegisterContextDBReg::eDREGTypeWATCH, i);
if (error.Fail()) {
m_hwp_regs[i].control = tempControl;
@@ -723,6 +735,7 @@ Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
return Status();
}
+#ifdef __arm__
unsigned int cap_val;
error = NativeProcessLinux::PtraceWrapper(PTRACE_GETHBPREGS, m_thread.GetID(),
@@ -737,16 +750,21 @@ Status NativeRegisterContextLinux_arm::ReadHardwareDebugInfo() {
m_refresh_hwdebug_info = false;
return error;
+#else // __aarch64__
+ return arm64::ReadHardwareDebugInfo(m_thread.GetID(), m_max_hwp_supported,
+ m_max_hbp_supported);
+#endif // ifdef __arm__
}
-Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
- int hwb_index) {
+Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(
+ NativeRegisterContextDBReg::DREGType hwbType, int hwb_index) {
Status error;
+#ifdef __arm__
lldb::addr_t *addr_buf;
uint32_t *ctrl_buf;
- if (hwbType == eDREGTypeWATCH) {
+ if (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH) {
addr_buf = &m_hwp_regs[hwb_index].address;
ctrl_buf = &m_hwp_regs[hwb_index].control;
@@ -781,6 +799,17 @@ Status NativeRegisterContextLinux_arm::WriteHardwareDebugRegs(int hwbType,
}
return error;
+#else // __aarch64__
+ uint32_t max_supported =
+ (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
+ ? m_max_hwp_supported
+ : m_max_hbp_supported;
+ auto &regs = (hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH)
+ ? m_hwp_regs
+ : m_hbr_regs;
+ return arm64::WriteHardwareDebugRegs(hwbType, m_thread.GetID(), max_supported,
+ regs);
+#endif // ifdef __arm__
}
uint32_t NativeRegisterContextLinux_arm::CalculateFprOffset(
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
index 15b4660..3a31d68 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm.h
@@ -12,6 +12,7 @@
#define lldb_NativeRegisterContextLinux_arm_h
#include "Plugins/Process/Linux/NativeRegisterContextLinux.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
#include "Plugins/Process/Utility/lldb-arm-register-enums.h"
@@ -74,9 +75,6 @@ public:
bool WatchpointIsEnabled(uint32_t wp_index);
- // Debug register type select
- enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
-
protected:
Status DoReadRegisterValue(uint32_t offset, const char *reg_name,
uint32_t size, RegisterValue &value) override;
@@ -102,18 +100,10 @@ private:
uint32_t m_gpr_arm[k_num_gpr_registers_arm];
RegisterInfoPOSIX_arm::FPU m_fpr;
- // Debug register info for hardware breakpoints and watchpoints management.
- struct DREG {
- lldb::addr_t address; // Breakpoint/watchpoint address value.
- lldb::addr_t hit_addr; // Address at which last watchpoint trigger exception
- // occurred.
- lldb::addr_t real_addr; // Address value that should cause target to stop.
- uint32_t control; // Breakpoint/watchpoint control value.
- uint32_t refcount; // Serves as enable/disable and reference counter.
- };
-
- struct DREG m_hbr_regs[16]; // Arm native linux hardware breakpoints
- struct DREG m_hwp_regs[16]; // Arm native linux hardware watchpoints
+ std::array<NativeRegisterContextDBReg::DREG, 16>
+ m_hbr_regs; // Arm native linux hardware breakpoints
+ std::array<NativeRegisterContextDBReg::DREG, 16>
+ m_hwp_regs; // Arm native linux hardware watchpoints
uint32_t m_max_hwp_supported;
uint32_t m_max_hbp_supported;
@@ -125,7 +115,8 @@ private:
Status ReadHardwareDebugInfo();
- Status WriteHardwareDebugRegs(int hwbType, int hwb_index);
+ Status WriteHardwareDebugRegs(NativeRegisterContextDBReg::DREGType hwbType,
+ int hwb_index);
uint32_t CalculateFprOffset(const RegisterInfo *reg_info) const;
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
index 884c7d4b..294a446 100644
--- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.cpp
@@ -8,8 +8,9 @@
#if defined(__arm64__) || defined(__aarch64__)
-#include "NativeRegisterContextLinux_arm.h"
#include "NativeRegisterContextLinux_arm64.h"
+#include "NativeRegisterContextLinux_arm.h"
+#include "NativeRegisterContextLinux_arm64dbreg.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
@@ -162,10 +163,13 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
opt_regsets.Set(RegisterInfoPOSIX_arm64::eRegsetMaskTLS);
+ std::optional<uint64_t> auxv_at_hwcap3 =
+ process.GetAuxValue(AuxVector::AUXV_AT_HWCAP3);
std::lock_guard<std::mutex> lock(g_register_flags_detector_mutex);
if (!g_register_flags_detector.HasDetected())
g_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
- auxv_at_hwcap2.value_or(0));
+ auxv_at_hwcap2.value_or(0),
+ auxv_at_hwcap3.value_or(0));
auto register_info_up =
std::make_unique<RegisterInfoPOSIX_arm64>(target_arch, opt_regsets);
@@ -1143,29 +1147,11 @@ llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
::pid_t tid = m_thread.GetID();
- int regset = NT_ARM_HW_WATCH;
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- Status error;
-
- ioVec.iov_base = &dreg_state;
- ioVec.iov_len = sizeof(dreg_state);
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
- &ioVec, ioVec.iov_len);
-
+ Status error = arm64::ReadHardwareDebugInfo(tid, m_max_hwp_supported,
+ m_max_hbp_supported);
if (error.Fail())
return error.ToError();
- m_max_hwp_supported = dreg_state.dbg_info & 0xff;
-
- regset = NT_ARM_HW_BREAK;
- error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
- &ioVec, ioVec.iov_len);
-
- if (error.Fail())
- return error.ToError();
-
- m_max_hbp_supported = dreg_state.dbg_info & 0xff;
m_refresh_hwdebug_info = false;
return llvm::Error::success();
@@ -1173,38 +1159,11 @@ llvm::Error NativeRegisterContextLinux_arm64::ReadHardwareDebugInfo() {
llvm::Error
NativeRegisterContextLinux_arm64::WriteHardwareDebugRegs(DREGType hwbType) {
- struct iovec ioVec;
- struct user_hwdebug_state dreg_state;
- int regset;
-
- memset(&dreg_state, 0, sizeof(dreg_state));
- ioVec.iov_base = &dreg_state;
-
- switch (hwbType) {
- case eDREGTypeWATCH:
- regset = NT_ARM_HW_WATCH;
- ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
- (sizeof(dreg_state.dbg_regs[0]) * m_max_hwp_supported);
-
- for (uint32_t i = 0; i < m_max_hwp_supported; i++) {
- dreg_state.dbg_regs[i].addr = m_hwp_regs[i].address;
- dreg_state.dbg_regs[i].ctrl = m_hwp_regs[i].control;
- }
- break;
- case eDREGTypeBREAK:
- regset = NT_ARM_HW_BREAK;
- ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
- (sizeof(dreg_state.dbg_regs[0]) * m_max_hbp_supported);
-
- for (uint32_t i = 0; i < m_max_hbp_supported; i++) {
- dreg_state.dbg_regs[i].addr = m_hbp_regs[i].address;
- dreg_state.dbg_regs[i].ctrl = m_hbp_regs[i].control;
- }
- break;
- }
-
- return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, m_thread.GetID(),
- &regset, &ioVec, ioVec.iov_len)
+ uint32_t max_supported =
+ (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported;
+ auto &regs = (hwbType == eDREGTypeWATCH) ? m_hwp_regs : m_hbp_regs;
+ return arm64::WriteHardwareDebugRegs(hwbType, m_thread.GetID(), max_supported,
+ regs)
.ToError();
}
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.cpp b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.cpp
new file mode 100644
index 0000000..53ee8fd
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.cpp
@@ -0,0 +1,77 @@
+//===-- NativeRegisterContextLinux_arm64dbreg.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
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__arm64__) || defined(__aarch64__)
+
+#include "NativeRegisterContextLinux_arm64dbreg.h"
+#include "lldb/Host/linux/Ptrace.h"
+
+#include <asm/ptrace.h>
+// System includes - They have to be included after framework includes because
+// they define some macros which collide with variable names in other modules
+#include <sys/uio.h>
+// NT_PRSTATUS and NT_FPREGSET definition
+#include <elf.h>
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_linux;
+
+static Status ReadHardwareDebugInfoHelper(int regset, ::pid_t tid,
+ uint32_t &max_supported) {
+ struct iovec ioVec;
+ struct user_hwdebug_state dreg_state;
+ Status error;
+
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof(dreg_state);
+ error = NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET, tid, &regset,
+ &ioVec, ioVec.iov_len);
+
+ if (error.Fail())
+ return error;
+
+ max_supported = dreg_state.dbg_info & 0xff;
+ return error;
+}
+
+Status lldb_private::process_linux::arm64::ReadHardwareDebugInfo(
+ ::pid_t tid, uint32_t &max_hwp_supported, uint32_t &max_hbp_supported) {
+ Status error =
+ ReadHardwareDebugInfoHelper(NT_ARM_HW_WATCH, tid, max_hwp_supported);
+
+ if (error.Fail())
+ return error;
+
+ return ReadHardwareDebugInfoHelper(NT_ARM_HW_BREAK, tid, max_hbp_supported);
+}
+
+Status lldb_private::process_linux::arm64::WriteHardwareDebugRegs(
+ int hwbType, ::pid_t tid, uint32_t max_supported,
+ const std::array<NativeRegisterContextDBReg::DREG, 16> &regs) {
+ int regset = hwbType == NativeRegisterContextDBReg::eDREGTypeWATCH
+ ? NT_ARM_HW_WATCH
+ : NT_ARM_HW_BREAK;
+
+ struct user_hwdebug_state dreg_state;
+ memset(&dreg_state, 0, sizeof(dreg_state));
+ for (uint32_t i = 0; i < max_supported; i++) {
+ dreg_state.dbg_regs[i].addr = regs[i].address;
+ dreg_state.dbg_regs[i].ctrl = regs[i].control;
+ }
+
+ struct iovec ioVec;
+ ioVec.iov_base = &dreg_state;
+ ioVec.iov_len = sizeof(dreg_state.dbg_info) + sizeof(dreg_state.pad) +
+ (sizeof(dreg_state.dbg_regs[0]) * max_supported);
+
+ return NativeProcessLinux::PtraceWrapper(PTRACE_SETREGSET, tid, &regset,
+ &ioVec, ioVec.iov_len);
+}
+
+#endif // defined (__arm64__) || defined (__aarch64__)
diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.h
new file mode 100644
index 0000000..bca2178
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64dbreg.h
@@ -0,0 +1,31 @@
+//===-- NativeRegisterContextLinux_arm64dbreg.h -----------------*- C++ -*-===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+
+// When debugging 32-bit processes, Arm64 lldb-server should use 64-bit ptrace
+// interfaces. 32-bit ptrace interfaces should only be used by 32-bit server.
+// These functions are split out to be reused in both 32-bit and 64-bit register
+// context for 64-bit server.
+
+#include "Plugins/Process/Linux/NativeProcessLinux.h"
+#include "Plugins/Process/Utility/NativeRegisterContextDBReg.h"
+#include "lldb/Utility/Status.h"
+
+namespace lldb_private {
+namespace process_linux {
+namespace arm64 {
+
+Status ReadHardwareDebugInfo(::pid_t tid, uint32_t &max_hwp_supported,
+ uint32_t &max_hbp_supported);
+
+Status WriteHardwareDebugRegs(
+ int hwbType, ::pid_t tid, uint32_t max_supported,
+ const std::array<NativeRegisterContextDBReg::DREG, 16> &regs);
+
+} // namespace arm64
+} // namespace process_linux
+} // namespace lldb_private
diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.cpp b/lldb/source/Plugins/Process/Utility/AuxVector.cpp
index f495ffb..d660bfe 100644
--- a/lldb/source/Plugins/Process/Utility/AuxVector.cpp
+++ b/lldb/source/Plugins/Process/Utility/AuxVector.cpp
@@ -84,6 +84,7 @@ const char *AuxVector::GetEntryName(EntryType type) const {
case ENTRY_NAME(AUXV_AT_BASE_PLATFORM); break;
case ENTRY_NAME(AUXV_AT_RANDOM); break;
case ENTRY_NAME(AUXV_AT_HWCAP2); break;
+ case ENTRY_NAME(AUXV_AT_HWCAP3); break;
case ENTRY_NAME(AUXV_AT_EXECFN); break;
case ENTRY_NAME(AUXV_AT_SYSINFO); break;
case ENTRY_NAME(AUXV_AT_SYSINFO_EHDR); break;
@@ -91,6 +92,8 @@ const char *AuxVector::GetEntryName(EntryType type) const {
case ENTRY_NAME(AUXV_AT_L1D_CACHESHAPE); break;
case ENTRY_NAME(AUXV_AT_L2_CACHESHAPE); break;
case ENTRY_NAME(AUXV_AT_L3_CACHESHAPE); break;
+ case ENTRY_NAME(AUXV_FREEBSD_AT_HWCAP3); break;
+ case ENTRY_NAME(AUXV_FREEBSD_AT_HWCAP4); break;
}
#undef ENTRY_NAME
diff --git a/lldb/source/Plugins/Process/Utility/AuxVector.h b/lldb/source/Plugins/Process/Utility/AuxVector.h
index 2670b34..ad6b70e 100644
--- a/lldb/source/Plugins/Process/Utility/AuxVector.h
+++ b/lldb/source/Plugins/Process/Utility/AuxVector.h
@@ -57,6 +57,7 @@ public:
AUXV_AT_BASE_PLATFORM = 24, ///< String identifying real platforms.
AUXV_AT_RANDOM = 25, ///< Address of 16 random bytes.
AUXV_AT_HWCAP2 = 26, ///< Extension of AT_HWCAP.
+ AUXV_AT_HWCAP3 = 29, ///< Extension of AT_HWCAP.
AUXV_AT_EXECFN = 31, ///< Filename of executable.
AUXV_AT_SYSINFO = 32, ///< Pointer to the global system page used for system
/// calls and other nice things.
@@ -69,6 +70,10 @@ public:
// Platform specific values which may overlap the Linux values.
AUXV_FREEBSD_AT_HWCAP = 25, ///< FreeBSD specific AT_HWCAP value.
+ // FreeBSD and Linux use the same AT_HWCAP2 value.
+ AUXV_FREEBSD_AT_HWCAP3 = 38, ///< FreeBSD specific AT_HWCAP3 value.
+ AUXV_FREEBSD_AT_HWCAP4 = 39, ///< FreeBSD specific AT_HWCAP4 value.
+
};
std::optional<uint64_t> GetAuxValue(enum EntryType entry_type) const;
diff --git a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
index e17a700..9b6ecd3 100644
--- a/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
+++ b/lldb/source/Plugins/Process/Utility/NativeRegisterContextDBReg.h
@@ -51,7 +51,6 @@ public:
lldb::addr_t GetWatchpointAddress(uint32_t wp_index) override;
-protected:
// Debug register type select
enum DREGType { eDREGTypeWATCH = 0, eDREGTypeBREAK };
@@ -64,6 +63,7 @@ protected:
uint32_t control; // Breakpoint/watchpoint control value.
};
+protected:
std::array<struct DREG, 16> m_hbp_regs; // hardware breakpoints
std::array<struct DREG, 16> m_hwp_regs; // hardware watchpoints
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
index 042940b..330a24a 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.cpp
@@ -26,11 +26,15 @@
#define HWCAP2_EBF16 (1ULL << 32)
#define HWCAP2_FPMR (1ULL << 48)
+#define HWCAP3_MTE_STORE_ONLY (1ULL << 1)
+
using namespace lldb_private;
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
+ (void)hwcap3;
if (!(hwcap2 & HWCAP2_FPMR))
return {};
@@ -53,8 +57,10 @@ Arm64RegisterFlagsDetector::DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2) {
Arm64RegisterFlagsDetector::Fields
Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
- uint64_t hwcap2) {
+ uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap2;
+ (void)hwcap3;
if (!(hwcap & HWCAP_GCS))
return {};
@@ -67,8 +73,10 @@ Arm64RegisterFlagsDetector::DetectGCSFeatureFields(uint64_t hwcap,
}
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
+ (void)hwcap3;
if (!(hwcap2 & HWCAP2_SME))
return {};
@@ -83,8 +91,8 @@ Arm64RegisterFlagsDetector::DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2) {
}
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
- uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
(void)hwcap;
if (!(hwcap2 & HWCAP2_MTE))
@@ -94,16 +102,29 @@ Arm64RegisterFlagsDetector::DetectMTECtrlFields(uint64_t hwcap,
// to prctl(PR_TAGGED_ADDR_CTRL...). Fields are derived from the defines
// used to build the value.
+ std::vector<RegisterFlags::Field> fields;
+ fields.reserve(4);
+ if (hwcap3 & HWCAP3_MTE_STORE_ONLY)
+ fields.push_back({"STORE_ONLY", 19});
+
static const FieldEnum tcf_enum(
"tcf_enum",
{{0, "TCF_NONE"}, {1, "TCF_SYNC"}, {2, "TCF_ASYNC"}, {3, "TCF_ASYMM"}});
- return {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT.
- {"TCF", 1, 2, &tcf_enum},
- {"TAGGED_ADDR_ENABLE", 0}};
+
+ fields.insert(
+ std::end(fields),
+ {{"TAGS", 3, 18}, // 16 bit bitfield shifted up by PR_MTE_TAG_SHIFT.
+ {"TCF", 1, 2, &tcf_enum},
+ {"TAGGED_ADDR_ENABLE", 0}});
+
+ return fields;
}
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
+ (void)hwcap3;
+
static const FieldEnum rmode_enum(
"rmode_enum", {{0, "RN"}, {1, "RP"}, {2, "RM"}, {3, "RZ"}});
@@ -142,10 +163,12 @@ Arm64RegisterFlagsDetector::DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2) {
}
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
// fpsr's contents are constant.
(void)hwcap;
(void)hwcap2;
+ (void)hwcap3;
return {
// Bits 31-28 are N/Z/C/V, only used by AArch32.
@@ -162,7 +185,10 @@ Arm64RegisterFlagsDetector::DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2) {
}
Arm64RegisterFlagsDetector::Fields
-Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
+Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
+ (void)hwcap3;
+
// The fields here are a combination of the Arm manual's SPSR_EL1,
// plus a few changes where Linux has decided not to make use of them at all,
// or at least not from userspace.
@@ -207,9 +233,10 @@ Arm64RegisterFlagsDetector::DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2) {
return cpsr_fields;
}
-void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2) {
+void Arm64RegisterFlagsDetector::DetectFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3) {
for (auto &reg : m_registers)
- reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2));
+ reg.m_flags.SetFields(reg.m_detector(hwcap, hwcap2, hwcap3));
m_has_detected = true;
}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
index 7daebcc..aec2bf9 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterFlagsDetector_arm64.h
@@ -40,7 +40,7 @@ public:
/// If called more than once, fields will be redetected each time from
/// scratch. If the target would not have this register at all, the list of
/// fields will be left empty.
- void DetectFields(uint64_t hwcap, uint64_t hwcap2);
+ void DetectFields(uint64_t hwcap, uint64_t hwcap2, uint64_t hwcap3);
/// Add the field information of any registers named in this class,
/// to the relevant RegisterInfo instances. Note that this will be done
@@ -53,15 +53,22 @@ public:
private:
using Fields = std::vector<RegisterFlags::Field>;
- using DetectorFn = std::function<Fields(uint64_t, uint64_t)>;
+ using DetectorFn = std::function<Fields(uint64_t, uint64_t, uint64_t)>;
- static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2);
- static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2);
+ static Fields DetectCPSRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectFPSRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectFPCRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectMTECtrlFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectSVCRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectFPMRFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
+ static Fields DetectGCSFeatureFields(uint64_t hwcap, uint64_t hwcap2,
+ uint64_t hwcap3);
struct RegisterEntry {
RegisterEntry(llvm::StringRef name, unsigned size, DetectorFn detector)
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
index bd02bb0..d5046d3 100644
--- a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_arm64.cpp
@@ -96,14 +96,19 @@ RegisterContextCorePOSIX_arm64::RegisterContextCorePOSIX_arm64(
llvm::Triple::OSType os = process->GetArchitecture().GetTriple().getOS();
if ((os == llvm::Triple::Linux) || (os == llvm::Triple::FreeBSD)) {
AuxVector aux_vec(process->GetAuxvData());
- std::optional<uint64_t> auxv_at_hwcap = aux_vec.GetAuxValue(
- os == llvm::Triple::FreeBSD ? AuxVector::AUXV_FREEBSD_AT_HWCAP
- : AuxVector::AUXV_AT_HWCAP);
+ bool is_freebsd = os == llvm::Triple::FreeBSD;
+ std::optional<uint64_t> auxv_at_hwcap =
+ aux_vec.GetAuxValue(is_freebsd ? AuxVector::AUXV_FREEBSD_AT_HWCAP
+ : AuxVector::AUXV_AT_HWCAP);
std::optional<uint64_t> auxv_at_hwcap2 =
aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP2);
+ std::optional<uint64_t> auxv_at_hwcap3 =
+ is_freebsd ? std::nullopt
+ : aux_vec.GetAuxValue(AuxVector::AUXV_AT_HWCAP3);
m_register_flags_detector.DetectFields(auxv_at_hwcap.value_or(0),
- auxv_at_hwcap2.value_or(0));
+ auxv_at_hwcap2.value_or(0),
+ auxv_at_hwcap3.value_or(0));
m_register_flags_detector.UpdateRegisterInfo(GetRegisterInfo(),
GetRegisterCount());
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index a2c34dd..f610422 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -323,6 +323,11 @@ ProcessGDBRemote::~ProcessGDBRemote() {
KillDebugserverProcess();
}
+std::shared_ptr<ThreadGDBRemote>
+ProcessGDBRemote::CreateThread(lldb::tid_t tid) {
+ return std::make_shared<ThreadGDBRemote>(*this, tid);
+}
+
bool ProcessGDBRemote::ParsePythonTargetDefinition(
const FileSpec &target_definition_fspec) {
ScriptInterpreter *interpreter =
@@ -1594,7 +1599,7 @@ bool ProcessGDBRemote::DoUpdateThreadList(ThreadList &old_thread_list,
ThreadSP thread_sp(
old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
if (!thread_sp) {
- thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid);
+ thread_sp = CreateThread(tid);
LLDB_LOGV(log, "Making new thread: {0} for thread ID: {1:x}.",
thread_sp.get(), thread_sp->GetID());
} else {
@@ -1726,7 +1731,7 @@ ThreadSP ProcessGDBRemote::SetThreadStopInfo(
if (!thread_sp) {
// Create the thread if we need to
- thread_sp = std::make_shared<ThreadGDBRemote>(*this, tid);
+ thread_sp = CreateThread(tid);
m_thread_list_real.AddThread(thread_sp);
}
}
@@ -4783,7 +4788,8 @@ bool ParseRegisters(
} else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") {
reg_info.format = eFormatAddressInfo;
reg_info.encoding = eEncodingUint;
- } else if (gdb_type == "float") {
+ } else if (gdb_type == "float" || gdb_type == "ieee_single" ||
+ gdb_type == "ieee_double") {
reg_info.format = eFormatFloat;
reg_info.encoding = eEncodingIEEE754;
} else if (gdb_type == "aarch64v" ||
@@ -5260,17 +5266,17 @@ llvm::Error ProcessGDBRemote::LoadModules() {
loaded_modules.Remove(removed_modules);
m_process->GetTarget().ModulesDidUnload(removed_modules, false);
- new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool {
+ new_modules.ForEach([&target](const lldb::ModuleSP module_sp) {
lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
if (!obj)
- return true;
+ return IterationAction::Continue;
if (obj->GetType() != ObjectFile::Type::eTypeExecutable)
- return true;
+ return IterationAction::Continue;
lldb::ModuleSP module_copy_sp = module_sp;
target.SetExecutableModule(module_copy_sp, eLoadDependentsNo);
- return false;
+ return IterationAction::Stop;
});
loaded_modules.AppendIfNeeded(new_modules);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 7ae3383..7c3dfb1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -246,6 +246,8 @@ protected:
ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+ virtual std::shared_ptr<ThreadGDBRemote> CreateThread(lldb::tid_t tid);
+
bool SupportsMemoryTagging() override;
/// Broadcaster event bits definitions.
diff --git a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
index 17a421a..b0b8fae 100644
--- a/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
+++ b/lldb/source/Plugins/Process/minidump/ProcessMinidump.cpp
@@ -408,7 +408,7 @@ void ProcessMinidump::BuildMemoryRegions() {
to_add.back().SetName(module_sp->GetFileSpec().GetPath().c_str());
}
}
- return true;
+ return IterationAction::Continue;
});
m_memory_regions->insert(m_memory_regions->end(), to_add.begin(),
to_add.end());
diff --git a/lldb/source/Plugins/Process/wasm/CMakeLists.txt b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
new file mode 100644
index 0000000..ff8a3c7
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt
@@ -0,0 +1,10 @@
+add_lldb_library(lldbPluginProcessWasm PLUGIN
+ ProcessWasm.cpp
+ ThreadWasm.cpp
+ UnwindWasm.cpp
+
+ LINK_LIBS
+ lldbCore
+ LINK_COMPONENTS
+ Support
+ )
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
new file mode 100644
index 0000000..5eeabec
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp
@@ -0,0 +1,133 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "ProcessWasm.h"
+#include "ThreadWasm.h"
+#include "lldb/Core/Module.h"
+#include "lldb/Core/PluginManager.h"
+#include "lldb/Core/Value.h"
+#include "lldb/Utility/DataBufferHeap.h"
+
+#include "lldb/Target/UnixSignals.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+using namespace lldb_private::wasm;
+
+LLDB_PLUGIN_DEFINE(ProcessWasm)
+
+ProcessWasm::ProcessWasm(lldb::TargetSP target_sp, ListenerSP listener_sp)
+ : ProcessGDBRemote(target_sp, listener_sp) {
+ assert(target_sp);
+ // Wasm doesn't have any Unix-like signals as a platform concept, but pretend
+ // like it does to appease LLDB.
+ m_unix_signals_sp = UnixSignals::Create(target_sp->GetArchitecture());
+}
+
+void ProcessWasm::Initialize() {
+ static llvm::once_flag g_once_flag;
+
+ llvm::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+ });
+}
+
+void ProcessWasm::DebuggerInitialize(Debugger &debugger) {
+ ProcessGDBRemote::DebuggerInitialize(debugger);
+}
+
+llvm::StringRef ProcessWasm::GetPluginName() { return GetPluginNameStatic(); }
+
+llvm::StringRef ProcessWasm::GetPluginNameStatic() { return "wasm"; }
+
+llvm::StringRef ProcessWasm::GetPluginDescriptionStatic() {
+ return "GDB Remote protocol based WebAssembly debugging plug-in.";
+}
+
+void ProcessWasm::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessWasm::CreateInstance);
+}
+
+lldb::ProcessSP ProcessWasm::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect) {
+ if (crash_file_path == nullptr)
+ return std::make_shared<ProcessWasm>(target_sp, listener_sp);
+ return {};
+}
+
+bool ProcessWasm::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ if (plugin_specified_by_name)
+ return true;
+
+ if (Module *exe_module = target_sp->GetExecutableModulePointer()) {
+ if (ObjectFile *exe_objfile = exe_module->GetObjectFile())
+ return exe_objfile->GetArchitecture().GetMachine() ==
+ llvm::Triple::wasm32;
+ }
+
+ // However, if there is no wasm module, we return false, otherwise,
+ // we might use ProcessWasm to attach gdb remote.
+ return false;
+}
+
+std::shared_ptr<ThreadGDBRemote> ProcessWasm::CreateThread(lldb::tid_t tid) {
+ return std::make_shared<ThreadWasm>(*this, tid);
+}
+
+size_t ProcessWasm::ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ Status &error) {
+ wasm_addr_t wasm_addr(vm_addr);
+
+ switch (wasm_addr.GetType()) {
+ case WasmAddressType::Memory:
+ case WasmAddressType::Object:
+ return ProcessGDBRemote::ReadMemory(vm_addr, buf, size, error);
+ case WasmAddressType::Invalid:
+ error.FromErrorStringWithFormat(
+ "Wasm read failed for invalid address 0x%" PRIx64, vm_addr);
+ return 0;
+ }
+}
+
+llvm::Expected<std::vector<lldb::addr_t>>
+ProcessWasm::GetWasmCallStack(lldb::tid_t tid) {
+ StreamString packet;
+ packet.Printf("qWasmCallStack:");
+ packet.Printf("%" PRIx64, tid);
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return llvm::createStringError("failed to send qWasmCallStack");
+
+ if (!response.IsNormalResponse())
+ return llvm::createStringError("failed to get response for qWasmCallStack");
+
+ WritableDataBufferSP data_buffer_sp =
+ std::make_shared<DataBufferHeap>(response.GetStringRef().size() / 2, 0);
+ const size_t bytes = response.GetHexBytes(data_buffer_sp->GetData(), '\xcc');
+ if (bytes == 0 || bytes % sizeof(uint64_t) != 0)
+ return llvm::createStringError("invalid response for qWasmCallStack");
+
+ // To match the Wasm specification, the addresses are encoded in little endian
+ // byte order.
+ DataExtractor data(data_buffer_sp, lldb::eByteOrderLittle,
+ GetAddressByteSize());
+ lldb::offset_t offset = 0;
+ std::vector<lldb::addr_t> call_stack_pcs;
+ while (offset < bytes)
+ call_stack_pcs.push_back(data.GetU64(&offset));
+
+ return call_stack_pcs;
+}
diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
new file mode 100644
index 0000000..bab14a8
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h
@@ -0,0 +1,91 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_PROCESSWASM_H
+
+#include "Plugins/Process/gdb-remote/ProcessGDBRemote.h"
+
+namespace lldb_private {
+namespace wasm {
+
+/// Each WebAssembly module has separated address spaces for Code and Memory.
+/// A WebAssembly module also has a Data section which, when the module is
+/// loaded, gets mapped into a region in the module Memory.
+enum WasmAddressType : uint8_t { Memory = 0x00, Object = 0x01, Invalid = 0xff };
+
+/// For the purpose of debugging, we can represent all these separated 32-bit
+/// address spaces with a single virtual 64-bit address space. The
+/// wasm_addr_t provides this encoding using bitfields.
+struct wasm_addr_t {
+ uint64_t offset : 32;
+ uint64_t module_id : 30;
+ uint64_t type : 2;
+
+ wasm_addr_t(lldb::addr_t addr)
+ : offset(addr & 0x00000000ffffffff),
+ module_id((addr & 0x00ffffff00000000) >> 32), type(addr >> 62) {}
+
+ wasm_addr_t(WasmAddressType type, uint32_t module_id, uint32_t offset)
+ : offset(offset), module_id(module_id), type(type) {}
+
+ WasmAddressType GetType() { return static_cast<WasmAddressType>(type); }
+
+ operator lldb::addr_t() { return *(uint64_t *)this; }
+};
+
+static_assert(sizeof(wasm_addr_t) == 8, "");
+
+/// ProcessWasm provides the access to the Wasm program state
+/// retrieved from the Wasm engine.
+class ProcessWasm : public process_gdb_remote::ProcessGDBRemote {
+public:
+ ProcessWasm(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+ ~ProcessWasm() override = default;
+
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path,
+ bool can_connect);
+
+ static void Initialize();
+ static void DebuggerInitialize(Debugger &debugger);
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic();
+ static llvm::StringRef GetPluginDescriptionStatic();
+
+ llvm::StringRef GetPluginName() override;
+
+ size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
+ Status &error) override;
+
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
+
+ /// Retrieve the current call stack from the WebAssembly remote process.
+ llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack(lldb::tid_t tid);
+
+protected:
+ std::shared_ptr<process_gdb_remote::ThreadGDBRemote>
+ CreateThread(lldb::tid_t tid) override;
+
+private:
+ friend class UnwindWasm;
+ process_gdb_remote::GDBRemoteDynamicRegisterInfoSP &GetRegisterInfo() {
+ return m_register_info_sp;
+ }
+
+ ProcessWasm(const ProcessWasm &);
+ const ProcessWasm &operator=(const ProcessWasm &) = delete;
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
new file mode 100644
index 0000000..a6553ff
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "ThreadWasm.h"
+
+#include "ProcessWasm.h"
+#include "UnwindWasm.h"
+#include "lldb/Target/Target.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::wasm;
+
+Unwind &ThreadWasm::GetUnwinder() {
+ if (!m_unwinder_up) {
+ assert(CalculateTarget()->GetArchitecture().GetMachine() ==
+ llvm::Triple::wasm32);
+ m_unwinder_up.reset(new wasm::UnwindWasm(*this));
+ }
+ return *m_unwinder_up;
+}
+
+llvm::Expected<std::vector<lldb::addr_t>> ThreadWasm::GetWasmCallStack() {
+ if (ProcessSP process_sp = GetProcess()) {
+ ProcessWasm *wasm_process = static_cast<ProcessWasm *>(process_sp.get());
+ return wasm_process->GetWasmCallStack(GetID());
+ }
+ return llvm::createStringError("no process");
+}
diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
new file mode 100644
index 0000000..1c90f58
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h
@@ -0,0 +1,38 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H
+
+#include "Plugins/Process/gdb-remote/ThreadGDBRemote.h"
+
+namespace lldb_private {
+namespace wasm {
+
+/// ProcessWasm provides the access to the Wasm program state
+/// retrieved from the Wasm engine.
+class ThreadWasm : public process_gdb_remote::ThreadGDBRemote {
+public:
+ ThreadWasm(Process &process, lldb::tid_t tid)
+ : process_gdb_remote::ThreadGDBRemote(process, tid) {}
+ ~ThreadWasm() override = default;
+
+ /// Retrieve the current call stack from the WebAssembly remote process.
+ llvm::Expected<std::vector<lldb::addr_t>> GetWasmCallStack();
+
+protected:
+ Unwind &GetUnwinder() override;
+
+ ThreadWasm(const ThreadWasm &);
+ const ThreadWasm &operator=(const ThreadWasm &) = delete;
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_WASM_THREADWASM_H
diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp
new file mode 100644
index 0000000..99845dd
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.cpp
@@ -0,0 +1,85 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "UnwindWasm.h"
+#include "Plugins/Process/gdb-remote/ThreadGDBRemote.h"
+#include "ProcessWasm.h"
+#include "ThreadWasm.h"
+#include "lldb/Utility/LLDBLog.h"
+#include "lldb/Utility/Log.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace process_gdb_remote;
+using namespace wasm;
+
+class WasmGDBRemoteRegisterContext : public GDBRemoteRegisterContext {
+public:
+ WasmGDBRemoteRegisterContext(ThreadGDBRemote &thread,
+ uint32_t concrete_frame_idx,
+ GDBRemoteDynamicRegisterInfoSP &reg_info_sp,
+ uint64_t pc)
+ : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false,
+ false) {
+ // Wasm does not have a fixed set of registers but relies on a mechanism
+ // named local and global variables to store information such as the stack
+ // pointer. The only actual register is the PC.
+ PrivateSetRegisterValue(0, pc);
+ }
+};
+
+lldb::RegisterContextSP
+UnwindWasm::DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) {
+ if (m_frames.size() <= frame->GetFrameIndex())
+ return lldb::RegisterContextSP();
+
+ ThreadSP thread = frame->GetThread();
+ ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *>(thread.get());
+ ProcessWasm *wasm_process =
+ static_cast<ProcessWasm *>(thread->GetProcess().get());
+
+ return std::make_shared<WasmGDBRemoteRegisterContext>(
+ *gdb_thread, frame->GetConcreteFrameIndex(),
+ wasm_process->GetRegisterInfo(), m_frames[frame->GetFrameIndex()]);
+}
+
+uint32_t UnwindWasm::DoGetFrameCount() {
+ if (m_unwind_complete)
+ return m_frames.size();
+
+ m_unwind_complete = true;
+ m_frames.clear();
+
+ ThreadWasm &wasm_thread = static_cast<ThreadWasm &>(GetThread());
+ llvm::Expected<std::vector<lldb::addr_t>> call_stack_pcs =
+ wasm_thread.GetWasmCallStack();
+ if (!call_stack_pcs) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Unwind), call_stack_pcs.takeError(),
+ "Failed to get Wasm callstack: {0}");
+ m_frames.clear();
+ return 0;
+ }
+
+ m_frames = *call_stack_pcs;
+ return m_frames.size();
+}
+
+bool UnwindWasm::DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
+ lldb::addr_t &pc,
+ bool &behaves_like_zeroth_frame) {
+ if (m_frames.size() == 0)
+ DoGetFrameCount();
+
+ if (frame_idx >= m_frames.size())
+ return false;
+
+ behaves_like_zeroth_frame = (frame_idx == 0);
+ cfa = 0;
+ pc = m_frames[frame_idx];
+ return true;
+}
diff --git a/lldb/source/Plugins/Process/wasm/UnwindWasm.h b/lldb/source/Plugins/Process/wasm/UnwindWasm.h
new file mode 100644
index 0000000..ff5e06d
--- /dev/null
+++ b/lldb/source/Plugins/Process/wasm/UnwindWasm.h
@@ -0,0 +1,51 @@
+//===----------------------------------------------------------------------===//
+//
+// 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_SOURCE_PLUGINS_PROCESS_WASM_UNWINDWASM_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_UNWINDWASM_H
+
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/Unwind.h"
+#include <vector>
+
+namespace lldb_private {
+namespace wasm {
+
+/// UnwindWasm manages stack unwinding for a WebAssembly process.
+class UnwindWasm : public lldb_private::Unwind {
+public:
+ UnwindWasm(lldb_private::Thread &thread) : Unwind(thread) {}
+ ~UnwindWasm() override = default;
+
+protected:
+ void DoClear() override {
+ m_frames.clear();
+ m_unwind_complete = false;
+ }
+
+ uint32_t DoGetFrameCount() override;
+
+ bool DoGetFrameInfoAtIndex(uint32_t frame_idx, lldb::addr_t &cfa,
+ lldb::addr_t &pc,
+ bool &behaves_like_zeroth_frame) override;
+
+ lldb::RegisterContextSP
+ DoCreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
+
+private:
+ std::vector<lldb::addr_t> m_frames;
+ bool m_unwind_complete = false;
+
+ UnwindWasm(const UnwindWasm &);
+ const UnwindWasm &operator=(const UnwindWasm &) = delete;
+};
+
+} // namespace wasm
+} // namespace lldb_private
+
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
index db9e11b..0437094 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/CMakeLists.txt
@@ -26,6 +26,7 @@ add_lldb_library(lldbPluginScriptInterpreterPythonInterfaces PLUGIN
ScriptedProcessPythonInterface.cpp
ScriptedPythonInterface.cpp
ScriptedStopHookPythonInterface.cpp
+ ScriptedBreakpointPythonInterface.cpp
ScriptedThreadPlanPythonInterface.cpp
ScriptedThreadPythonInterface.cpp
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
index 1fd3299..d43036d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.cpp
@@ -29,6 +29,7 @@ void ScriptInterpreterPythonInterfaces::Initialize() {
ScriptedPlatformPythonInterface::Initialize();
ScriptedProcessPythonInterface::Initialize();
ScriptedStopHookPythonInterface::Initialize();
+ ScriptedBreakpointPythonInterface::Initialize();
ScriptedThreadPlanPythonInterface::Initialize();
}
@@ -37,6 +38,7 @@ void ScriptInterpreterPythonInterfaces::Terminate() {
ScriptedPlatformPythonInterface::Terminate();
ScriptedProcessPythonInterface::Terminate();
ScriptedStopHookPythonInterface::Terminate();
+ ScriptedBreakpointPythonInterface::Terminate();
ScriptedThreadPlanPythonInterface::Terminate();
}
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
index 26c80b7..02dc065 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptInterpreterPythonInterfaces.h
@@ -16,6 +16,7 @@
#if LLDB_ENABLE_PYTHON
#include "OperatingSystemPythonInterface.h"
+#include "ScriptedBreakpointPythonInterface.h"
#include "ScriptedPlatformPythonInterface.h"
#include "ScriptedProcessPythonInterface.h"
#include "ScriptedStopHookPythonInterface.h"
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp
new file mode 100644
index 0000000..660edaa
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.cpp
@@ -0,0 +1,100 @@
+//===----------------------------------------------------------------------===//
+//
+// 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 "lldb/Core/PluginManager.h"
+#include "lldb/Host/Config.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Target/ExecutionContext.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/lldb-enumerations.h"
+
+#if LLDB_ENABLE_PYTHON
+
+// LLDB Python header must be included first
+#include "../lldb-python.h"
+
+#include "../SWIGPythonBridge.h"
+#include "../ScriptInterpreterPythonImpl.h"
+#include "ScriptedBreakpointPythonInterface.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::python;
+
+ScriptedBreakpointPythonInterface::ScriptedBreakpointPythonInterface(
+ ScriptInterpreterPythonImpl &interpreter)
+ : ScriptedBreakpointInterface(), ScriptedPythonInterface(interpreter) {}
+
+llvm::Expected<StructuredData::GenericSP>
+ScriptedBreakpointPythonInterface::CreatePluginObject(
+ llvm::StringRef class_name, lldb::BreakpointSP break_sp,
+ const StructuredDataImpl &args_sp) {
+ return ScriptedPythonInterface::CreatePluginObject(class_name, nullptr,
+ break_sp, args_sp);
+}
+
+bool ScriptedBreakpointPythonInterface::ResolverCallback(
+ SymbolContext sym_ctx) {
+ Status error;
+
+ StructuredData::ObjectSP obj = Dispatch("__callback__", error, sym_ctx);
+
+ if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
+ error)) {
+ Log *log = GetLog(LLDBLog::Script);
+ LLDB_LOG(log, "Error calling __callback__ method: {1}", error);
+ return true;
+ }
+ return obj->GetBooleanValue();
+}
+
+lldb::SearchDepth ScriptedBreakpointPythonInterface::GetDepth() {
+ Status error;
+ StructuredData::ObjectSP obj = Dispatch("__get_depth__", error);
+
+ if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
+ error)) {
+ return lldb::eSearchDepthModule;
+ }
+ uint64_t value = obj->GetUnsignedIntegerValue();
+ if (value <= lldb::kLastSearchDepthKind)
+ return (lldb::SearchDepth)value;
+ // This is what we were doing on error before, though I'm not sure that's
+ // better than returning eSearchDepthInvalid.
+ return lldb::eSearchDepthModule;
+}
+
+std::optional<std::string> ScriptedBreakpointPythonInterface::GetShortHelp() {
+ Status error;
+ StructuredData::ObjectSP obj = Dispatch("get_short_help", error);
+
+ if (!ScriptedInterface::CheckStructuredDataObject(LLVM_PRETTY_FUNCTION, obj,
+ error)) {
+ return {};
+ }
+
+ return obj->GetAsString()->GetValue().str();
+}
+
+void ScriptedBreakpointPythonInterface::Initialize() {
+ const std::vector<llvm::StringRef> ci_usages = {
+ "breakpoint set -P classname [-k key -v value ...]"};
+ const std::vector<llvm::StringRef> api_usages = {
+ "SBTarget.BreakpointCreateFromScript"};
+ PluginManager::RegisterPlugin(
+ GetPluginNameStatic(),
+ llvm::StringRef("Create a breakpoint that chooses locations based on "
+ "user-created callbacks"),
+ CreateInstance, eScriptLanguagePython, {ci_usages, api_usages});
+}
+
+void ScriptedBreakpointPythonInterface::Terminate() {
+ PluginManager::UnregisterPlugin(CreateInstance);
+}
+
+#endif
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h
new file mode 100644
index 0000000..27bdd871
--- /dev/null
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedBreakpointPythonInterface.h
@@ -0,0 +1,53 @@
+//===-- ScriptedBreakpointPythonInterface.h -----------------------*- C++
+//-*-===//
+//
+// 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_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
+#define LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
+
+#include "lldb/Host/Config.h"
+#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
+
+#if LLDB_ENABLE_PYTHON
+
+#include "ScriptedPythonInterface.h"
+
+namespace lldb_private {
+class ScriptedBreakpointPythonInterface : public ScriptedBreakpointInterface,
+ public ScriptedPythonInterface,
+ public PluginInterface {
+public:
+ ScriptedBreakpointPythonInterface(ScriptInterpreterPythonImpl &interpreter);
+
+ llvm::Expected<StructuredData::GenericSP>
+ CreatePluginObject(llvm::StringRef class_name, lldb::BreakpointSP break_sp,
+ const StructuredDataImpl &args_sp) override;
+
+ llvm::SmallVector<AbstractMethodRequirement>
+ GetAbstractMethodRequirements() const override {
+ return llvm::SmallVector<AbstractMethodRequirement>({{"__callback__", 2}});
+ }
+
+ bool ResolverCallback(SymbolContext sym_ctx) override;
+ lldb::SearchDepth GetDepth() override;
+ std::optional<std::string> GetShortHelp() override;
+
+ static void Initialize();
+
+ static void Terminate();
+
+ static llvm::StringRef GetPluginNameStatic() {
+ return "ScriptedBreakpointPythonInterface";
+ }
+
+ llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
+};
+} // namespace lldb_private
+
+#endif // LLDB_ENABLE_PYTHON
+#endif // LLDB_PLUGINS_SCRIPTINTERPRETER_PYTHON_INTERFACES_SCRIPTEDBREAKPOINTPYTHONINTERFACE_H
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
index cf11c06..b49d1d8 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.cpp
@@ -17,6 +17,7 @@
#include "../ScriptInterpreterPythonImpl.h"
#include "ScriptedPythonInterface.h"
+#include "lldb/Symbol/SymbolContext.h"
#include <optional>
using namespace lldb;
@@ -80,6 +81,20 @@ ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
}
template <>
+SymbolContext
+ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
+ python::PythonObject &p, Status &error) {
+ if (lldb::SBSymbolContext *sb_symbol_context =
+ reinterpret_cast<lldb::SBSymbolContext *>(
+ python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(p.get())))
+ return m_interpreter.GetOpaqueTypeFromSBSymbolContext(*sb_symbol_context);
+ error = Status::FromErrorString(
+ "Couldn't cast lldb::SBSymbolContext to lldb_private::SymbolContext.");
+
+ return {};
+}
+
+template <>
lldb::DataExtractorSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::DataExtractorSP>(
python::PythonObject &p, Status &error) {
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
index b38b65e..f769d3d 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/Interfaces/ScriptedPythonInterface.h
@@ -432,6 +432,10 @@ protected:
return python::SWIGBridge::ToSWIGWrapper(arg);
}
+ python::PythonObject Transform(lldb::BreakpointSP arg) {
+ return python::SWIGBridge::ToSWIGWrapper(arg);
+ }
+
python::PythonObject Transform(lldb::ProcessSP arg) {
return python::SWIGBridge::ToSWIGWrapper(arg);
}
@@ -452,6 +456,10 @@ protected:
return python::SWIGBridge::ToSWIGWrapper(arg);
}
+ python::PythonObject Transform(const SymbolContext &arg) {
+ return python::SWIGBridge::ToSWIGWrapper(arg);
+ }
+
python::PythonObject Transform(lldb::StreamSP arg) {
return python::SWIGBridge::ToSWIGWrapper(arg.get());
}
@@ -556,6 +564,11 @@ Event *ScriptedPythonInterface::ExtractValueFromPythonObject<Event *>(
python::PythonObject &p, Status &error);
template <>
+SymbolContext
+ScriptedPythonInterface::ExtractValueFromPythonObject<SymbolContext>(
+ python::PythonObject &p, Status &error);
+
+template <>
lldb::StreamSP
ScriptedPythonInterface::ExtractValueFromPythonObject<lldb::StreamSP>(
python::PythonObject &p, Status &error);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
index 504b3aa..4137786 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h
@@ -151,15 +151,6 @@ public:
const char *session_dictionary_name,
lldb::DebuggerSP debugger_sp);
- static python::PythonObject LLDBSwigPythonCreateScriptedBreakpointResolver(
- const char *python_class_name, const char *session_dictionary_name,
- const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp);
-
- static unsigned int
- LLDBSwigPythonCallBreakpointResolver(void *implementor,
- const char *method_name,
- lldb_private::SymbolContext *sym_ctx);
-
static size_t LLDBSwigPython_CalculateNumChildren(PyObject *implementor,
uint32_t max);
@@ -270,6 +261,7 @@ void *LLDBSWIGPython_CastPyObjectToSBLaunchInfo(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBError(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBEvent(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data);
+void *LLDBSWIGPython_CastPyObjectToSBSymbolContext(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBMemoryRegionInfo(PyObject *data);
void *LLDBSWIGPython_CastPyObjectToSBExecutionContext(PyObject *data);
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
index 0c864dc..ce77569 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp
@@ -1496,7 +1496,7 @@ lldb::ValueObjectListSP ScriptInterpreterPythonImpl::GetRecognizedArguments(
}
if (py_return.get()) {
PythonList result_list(PyRefType::Borrowed, py_return.get());
- ValueObjectListSP result = ValueObjectListSP(new ValueObjectList());
+ ValueObjectListSP result = std::make_shared<ValueObjectList>();
for (size_t i = 0; i < result_list.GetSize(); i++) {
PyObject *item = result_list.GetItemAtIndex(i).get();
lldb::SBValue *sb_value_ptr =
@@ -1550,6 +1550,11 @@ ScriptInterpreterPythonImpl::CreateScriptedStopHookInterface() {
return std::make_shared<ScriptedStopHookPythonInterface>(*this);
}
+ScriptedBreakpointInterfaceSP
+ScriptInterpreterPythonImpl::CreateScriptedBreakpointInterface() {
+ return std::make_shared<ScriptedBreakpointPythonInterface>(*this);
+}
+
ScriptedThreadInterfaceSP
ScriptInterpreterPythonImpl::CreateScriptedThreadInterface() {
return std::make_shared<ScriptedThreadPythonInterface>(*this);
@@ -1576,75 +1581,6 @@ ScriptInterpreterPythonImpl::CreateStructuredDataFromScriptObject(
return py_obj.CreateStructuredObject();
}
-StructuredData::GenericSP
-ScriptInterpreterPythonImpl::CreateScriptedBreakpointResolver(
- const char *class_name, const StructuredDataImpl &args_data,
- lldb::BreakpointSP &bkpt_sp) {
-
- if (class_name == nullptr || class_name[0] == '\0')
- return StructuredData::GenericSP();
-
- if (!bkpt_sp.get())
- return StructuredData::GenericSP();
-
- Debugger &debugger = bkpt_sp->GetTarget().GetDebugger();
- ScriptInterpreterPythonImpl *python_interpreter =
- GetPythonInterpreter(debugger);
-
- if (!python_interpreter)
- return StructuredData::GenericSP();
-
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
-
- PythonObject ret_val =
- SWIGBridge::LLDBSwigPythonCreateScriptedBreakpointResolver(
- class_name, python_interpreter->m_dictionary_name.c_str(), args_data,
- bkpt_sp);
-
- return StructuredData::GenericSP(
- new StructuredPythonObject(std::move(ret_val)));
-}
-
-bool ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchCallback(
- StructuredData::GenericSP implementor_sp, SymbolContext *sym_ctx) {
- bool should_continue = false;
-
- if (implementor_sp) {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- should_continue = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
- implementor_sp->GetValue(), "__callback__", sym_ctx);
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- }
- }
- return should_continue;
-}
-
-lldb::SearchDepth
-ScriptInterpreterPythonImpl::ScriptedBreakpointResolverSearchDepth(
- StructuredData::GenericSP implementor_sp) {
- int depth_as_int = lldb::eSearchDepthModule;
- if (implementor_sp) {
- Locker py_lock(this,
- Locker::AcquireLock | Locker::InitSession | Locker::NoSTDIN);
- depth_as_int = SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
- implementor_sp->GetValue(), "__get_depth__", nullptr);
- if (PyErr_Occurred()) {
- PyErr_Print();
- PyErr_Clear();
- }
- }
- if (depth_as_int == lldb::eSearchDepthInvalid)
- return lldb::eSearchDepthModule;
-
- if (depth_as_int <= lldb::kLastSearchDepthKind)
- return (lldb::SearchDepth)depth_as_int;
- return lldb::eSearchDepthModule;
-}
-
StructuredData::ObjectSP
ScriptInterpreterPythonImpl::LoadPluginModule(const FileSpec &file_spec,
lldb_private::Status &error) {
@@ -3047,7 +2983,7 @@ bool ScriptInterpreterPythonImpl::SetOptionValueForCommandObject(
lldb::ExecutionContextRefSP exe_ctx_ref_sp;
if (exe_ctx)
- exe_ctx_ref_sp.reset(new ExecutionContextRef(exe_ctx));
+ exe_ctx_ref_sp = std::make_shared<ExecutionContextRef>(exe_ctx);
PythonObject ctx_ref_obj = SWIGBridge::ToSWIGWrapper(exe_ctx_ref_sp);
bool py_return = unwrapOrSetPythonException(As<bool>(
diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
index 5d77608..4698b82a 100644
--- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
+++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h
@@ -81,17 +81,6 @@ public:
CreateStructuredDataFromScriptObject(ScriptObject obj) override;
StructuredData::GenericSP
- CreateScriptedBreakpointResolver(const char *class_name,
- const StructuredDataImpl &args_data,
- lldb::BreakpointSP &bkpt_sp) override;
- bool ScriptedBreakpointResolverSearchCallback(
- StructuredData::GenericSP implementor_sp,
- SymbolContext *sym_ctx) override;
-
- lldb::SearchDepth ScriptedBreakpointResolverSearchDepth(
- StructuredData::GenericSP implementor_sp) override;
-
- StructuredData::GenericSP
CreateFrameRecognizer(const char *class_name) override;
lldb::ValueObjectListSP
@@ -105,6 +94,9 @@ public:
lldb::ScriptedStopHookInterfaceSP CreateScriptedStopHookInterface() override;
+ lldb::ScriptedBreakpointInterfaceSP
+ CreateScriptedBreakpointInterface() override;
+
lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() override;
lldb::ScriptedThreadPlanInterfaceSP
diff --git a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
index 82f18c5..867f6a6 100644
--- a/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
+++ b/lldb/source/Plugins/StructuredData/DarwinLog/StructuredDataDarwinLog.cpp
@@ -574,8 +574,7 @@ public:
return config_sp;
// Handle source stream flags.
- auto source_flags_sp =
- StructuredData::DictionarySP(new StructuredData::Dictionary());
+ auto source_flags_sp = std::make_shared<StructuredData::Dictionary>();
config_sp->AddItem("source-flags", source_flags_sp);
source_flags_sp->AddBooleanItem("any-process", m_include_any_process);
@@ -591,8 +590,7 @@ public:
// Handle filter rules
if (!m_filter_rules.empty()) {
- auto json_filter_rules_sp =
- StructuredData::ArraySP(new StructuredData::Array);
+ auto json_filter_rules_sp = std::make_shared<StructuredData::Array>();
config_sp->AddItem("filter-rules", json_filter_rules_sp);
for (auto &rule_sp : m_filter_rules) {
if (!rule_sp)
diff --git a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
index e5ba029..1e51dda 100644
--- a/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
+++ b/lldb/source/Plugins/SymbolLocator/DebugSymbols/SymbolLocatorDebugSymbols.cpp
@@ -46,6 +46,7 @@
#include <cstring>
#include <dirent.h>
#include <dlfcn.h>
+#include <memory>
#include <optional>
#include <pwd.h>
@@ -188,7 +189,7 @@ std::optional<ModuleSpec> SymbolLocatorDebugSymbols::LocateExecutableObjectFile(
exe_spec.GetFileSpec() = module_spec.GetFileSpec();
exe_spec.GetUUID() = module_spec.GetUUID();
ModuleSP module_sp;
- module_sp.reset(new Module(exe_spec));
+ module_sp = std::make_shared<Module>(exe_spec);
if (module_sp && module_sp->GetObjectFile() &&
module_sp->MatchesModuleSpec(exe_spec)) {
success = true;
@@ -630,7 +631,7 @@ static int LocateMacOSXFilesUsingDebugSymbols(const ModuleSpec &module_spec,
exe_spec.GetFileSpec() = module_spec.GetFileSpec();
exe_spec.GetUUID() = module_spec.GetUUID();
ModuleSP module_sp;
- module_sp.reset(new Module(exe_spec));
+ module_sp = std::make_shared<Module>(exe_spec);
if (module_sp && module_sp->GetObjectFile() &&
module_sp->MatchesModuleSpec(exe_spec)) {
success = true;
diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp
index 7cf8750..aaa4ccd 100644
--- a/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp
+++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AbortWithPayloadFrameRecognizer.cpp
@@ -128,7 +128,7 @@ AbortWithPayloadFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame_sp) {
Value *cur_value;
StackFrame *frame = frame_sp.get();
- ValueObjectListSP arguments_sp = ValueObjectListSP(new ValueObjectList());
+ ValueObjectListSP arguments_sp = std::make_shared<ValueObjectList>();
auto add_to_arguments = [&](llvm::StringRef name, Value *value,
bool dynamic) {
diff --git a/lldb/source/Symbol/Type.cpp b/lldb/source/Symbol/Type.cpp
index 0a886e5..b7adae4 100644
--- a/lldb/source/Symbol/Type.cpp
+++ b/lldb/source/Symbol/Type.cpp
@@ -9,6 +9,7 @@
#include <algorithm>
#include <cstdio>
#include <iterator>
+#include <memory>
#include <optional>
#include "lldb/Core/Module.h"
@@ -246,7 +247,7 @@ public:
TypeAppendVisitor(TypeListImpl &type_list) : m_type_list(type_list) {}
bool operator()(const lldb::TypeSP &type) {
- m_type_list.Append(TypeImplSP(new TypeImpl(type)));
+ m_type_list.Append(std::make_shared<TypeImpl>(type));
return true;
}
diff --git a/lldb/source/Target/InstrumentationRuntime.cpp b/lldb/source/Target/InstrumentationRuntime.cpp
index 9da06e8..7e58e8b 100644
--- a/lldb/source/Target/InstrumentationRuntime.cpp
+++ b/lldb/source/Target/InstrumentationRuntime.cpp
@@ -49,10 +49,10 @@ void InstrumentationRuntime::ModulesDidLoad(
return;
}
- module_list.ForEach([this](const lldb::ModuleSP module_sp) -> bool {
+ module_list.ForEach([this](const lldb::ModuleSP module_sp) {
const FileSpec &file_spec = module_sp->GetFileSpec();
if (!file_spec)
- return true; // Keep iterating.
+ return IterationAction::Continue;
const RegularExpression &runtime_regex = GetPatternForRuntimeLibrary();
if (runtime_regex.Execute(file_spec.GetFilename().GetCString()) ||
@@ -62,16 +62,16 @@ void InstrumentationRuntime::ModulesDidLoad(
Activate();
if (!IsActive())
SetRuntimeModuleSP({}); // Don't cache module if activation failed.
- return false; // Stop iterating, we're done.
+ return IterationAction::Stop;
}
}
- return true;
+ return IterationAction::Continue;
});
}
lldb::ThreadCollectionSP
InstrumentationRuntime::GetBacktracesFromExtendedStopInfo(
StructuredData::ObjectSP info) {
- return ThreadCollectionSP(new ThreadCollection());
+ return std::make_shared<ThreadCollection>();
}
diff --git a/lldb/source/Target/Platform.cpp b/lldb/source/Target/Platform.cpp
index 8000cd0..e9d9c8f 100644
--- a/lldb/source/Target/Platform.cpp
+++ b/lldb/source/Target/Platform.cpp
@@ -2076,6 +2076,13 @@ size_t Platform::GetSoftwareBreakpointTrapOpcode(Target &target,
trap_opcode_size = sizeof(g_loongarch_opcode);
} break;
+ case llvm::Triple::wasm32: {
+ // Unreachable (0x00) triggers an unconditional trap.
+ static const uint8_t g_wasm_opcode[] = {0x00};
+ trap_opcode = g_wasm_opcode;
+ trap_opcode_size = sizeof(g_wasm_opcode);
+ } break;
+
default:
return 0;
}
diff --git a/lldb/source/Target/StackFrameList.cpp b/lldb/source/Target/StackFrameList.cpp
index 16cd254..aedfc52 100644
--- a/lldb/source/Target/StackFrameList.cpp
+++ b/lldb/source/Target/StackFrameList.cpp
@@ -783,6 +783,8 @@ void StackFrameList::SelectMostRelevantFrame() {
uint32_t
StackFrameList::GetSelectedFrameIndex(SelectMostRelevant select_most_relevant) {
+ std::lock_guard<std::recursive_mutex> guard(m_selected_frame_mutex);
+
if (!m_selected_frame_idx && select_most_relevant)
SelectMostRelevantFrame();
if (!m_selected_frame_idx) {
@@ -798,6 +800,8 @@ StackFrameList::GetSelectedFrameIndex(SelectMostRelevant select_most_relevant) {
uint32_t StackFrameList::SetSelectedFrame(lldb_private::StackFrame *frame) {
std::shared_lock<std::shared_mutex> guard(m_list_mutex);
+ std::lock_guard<std::recursive_mutex> selected_frame_guard(
+ m_selected_frame_mutex);
const_iterator pos;
const_iterator begin = m_frames.begin();
@@ -851,6 +855,8 @@ void StackFrameList::Clear() {
std::unique_lock<std::shared_mutex> guard(m_list_mutex);
m_frames.clear();
m_concrete_frames_fetched = 0;
+ std::lock_guard<std::recursive_mutex> selected_frame_guard(
+ m_selected_frame_mutex);
m_selected_frame_idx.reset();
}
diff --git a/lldb/source/Target/StackFrameRecognizer.cpp b/lldb/source/Target/StackFrameRecognizer.cpp
index d23c1fa..9d5116c 100644
--- a/lldb/source/Target/StackFrameRecognizer.cpp
+++ b/lldb/source/Target/StackFrameRecognizer.cpp
@@ -41,7 +41,7 @@ ScriptedStackFrameRecognizer::RecognizeFrame(lldb::StackFrameSP frame) {
ValueObjectListSP args =
m_interpreter->GetRecognizedArguments(m_python_object_sp, frame);
- auto args_synthesized = ValueObjectListSP(new ValueObjectList());
+ auto args_synthesized = std::make_shared<ValueObjectList>();
if (args) {
for (const auto &o : args->GetObjects())
args_synthesized->Append(ValueObjectRecognizerSynthesizedValue::Create(
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index 86ae7dd..4f39f60 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -36,6 +36,7 @@
#include "lldb/Host/StreamFile.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h"
+#include "lldb/Interpreter/Interfaces/ScriptedBreakpointInterface.h"
#include "lldb/Interpreter/Interfaces/ScriptedStopHookInterface.h"
#include "lldb/Interpreter/OptionGroupWatchpoint.h"
#include "lldb/Interpreter/OptionValues.h"
@@ -2487,9 +2488,9 @@ ModuleSP Target::GetOrCreateModule(const ModuleSpec &orig_module_spec,
ModuleList found_modules;
m_images.FindModules(module_spec_copy, found_modules);
- found_modules.ForEach([&](const ModuleSP &found_module) -> bool {
+ found_modules.ForEach([&](const ModuleSP &found_module) {
old_modules.push_back(found_module);
- return true;
+ return IterationAction::Continue;
});
}
diff --git a/lldb/source/Target/ThreadPlanStepRange.cpp b/lldb/source/Target/ThreadPlanStepRange.cpp
index 78e1270..dca96cc 100644
--- a/lldb/source/Target/ThreadPlanStepRange.cpp
+++ b/lldb/source/Target/ThreadPlanStepRange.cpp
@@ -428,8 +428,8 @@ bool ThreadPlanStepRange::SetNextBranchBreakpoint() {
top_most_line_entry.line = call_site.GetLine();
top_most_line_entry.column = call_site.GetColumn();
FileSpec call_site_file_spec = call_site.GetFile();
- top_most_line_entry.original_file_sp.reset(
- new SupportFile(call_site_file_spec));
+ top_most_line_entry.original_file_sp =
+ std::make_shared<SupportFile>(call_site_file_spec);
top_most_line_entry.range = range;
top_most_line_entry.file_sp.reset();
top_most_line_entry.ApplyFileMappings(
diff --git a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
index 2570f26..c003d87 100644
--- a/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
+++ b/lldb/test/API/commands/register/register/aarch64_mte_ctrl_register/TestMTECtrlRegister.py
@@ -34,29 +34,41 @@ class MTECtrlRegisterTestCase(TestBase):
substrs=["stop reason = breakpoint 1."],
)
- def check_mte_ctrl(async_err, sync_err):
+ has_store_only = self.isAArch64MTEStoreOnly()
+
+ def check_mte_ctrl(async_err, sync_err, store_only):
# Bit 0 = tagged addressing enabled
# Bit 1 = synchronous faults
# Bit 2 = asynchronous faults
- value = "0x{:016x}".format((async_err << 2) | (sync_err << 1) | 1)
+ # Bit 19 = store only checking mode
+ value = "0x{:016x}".format(
+ (store_only << 19) | (async_err << 2) | (sync_err << 1) | 1
+ )
expected = [value]
if self.hasXMLSupport():
+ fields = "("
+ if has_store_only:
+ fields += f"STORE_ONLY = {store_only}, "
+
tfc_modes = ["NONE", "SYNC", "ASYNC", "ASYMM"]
- expected.append(
- f"(TAGS = 0, TCF = TCF_{tfc_modes[async_err << 1 | sync_err]}, TAGGED_ADDR_ENABLE = 1)".format(
- async_err, sync_err
- )
- )
+ fields += f"TAGS = 0, TCF = TCF_{tfc_modes[async_err << 1 | sync_err]}, TAGGED_ADDR_ENABLE = 1)"
+
+ expected.append(fields)
self.expect("register read mte_ctrl", substrs=expected)
# We start enabled with synchronous faults.
- check_mte_ctrl(0, 1)
+ check_mte_ctrl(0, 1, 0)
# Change to asynchronous faults.
self.runCmd("register write mte_ctrl 5")
- check_mte_ctrl(1, 0)
+ check_mte_ctrl(1, 0, 0)
# This would return to synchronous faults if we did not restore the
# previous value.
self.expect("expression setup_mte()", substrs=["= 0"])
- check_mte_ctrl(1, 0)
+ check_mte_ctrl(1, 0, 0)
+
+ # Store only checking requires FEAT_MTE_STORE_ONLY.
+ if has_store_only:
+ self.runCmd(f"register write mte_ctrl {1 | (1 << 19)}")
+ check_mte_ctrl(0, 0, 1)
diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
index 0a1003a..634940d 100644
--- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
+++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/TestScriptedResolver.py
@@ -235,11 +235,13 @@ class TestScriptedResolver(TestBase):
substrs=["2"],
msg="Was only passed modules",
)
-
+ print(f"Made first breakpoint: {bkpt}")
+ bkpt = None
# Make a breakpoint that asks for modules, check that we didn't get any files:
bkpt = target.BreakpointCreateFromScript(
"resolver.ResolverModuleDepth", extra_args, module_list, file_list
)
+ print(f"Made Second breakpoint: {bkpt}")
self.assertGreater(
bkpt.GetNumLocations(), 0, "ResolverModuleDepth got no locations."
)
diff --git a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py
index 8b91702..85c73401 100644
--- a/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py
+++ b/lldb/test/API/functionalities/breakpoint/scripted_bkpt/resolver.py
@@ -13,6 +13,7 @@ class Resolver:
Resolver.got_files = 0
def __callback__(self, sym_ctx):
+ print("Resolver callback called")
sym_name = "not_a_real_function_name"
sym_item = self.extra_args.GetValueForKey("symbol")
if sym_item.IsValid():
@@ -34,9 +35,18 @@ class Resolver:
return
if sym_ctx.module.IsValid():
+ print(f"Looking for {sym_name}")
sym = sym_ctx.module.FindSymbol(sym_name, lldb.eSymbolTypeCode)
if sym.IsValid():
+ print(f"Adding location at {sym.GetStartAddress()} to {self.bkpt}")
self.bkpt.AddLocation(sym.GetStartAddress())
+ print(f"After addition: {self.bkpt}")
+ else:
+ print("Didn't find it, however...")
+
+ print(f"GotFiles: {Resolver.got_files}")
+ for func in Resolver.func_list:
+ print(f"Function: func")
def get_short_help(self):
return "I am a python breakpoint resolver"
@@ -46,17 +56,31 @@ class ResolverModuleDepth(Resolver):
def __get_depth__(self):
return lldb.eSearchDepthModule
+ def __callback__(self, sym_ctx):
+ print(f"About to call the Resolver callback for {self.bkpt}")
+ Resolver.__callback__(self, sym_ctx)
+ print("Called the callback for ResolverModuleDepth")
+
class ResolverCUDepth(Resolver):
def __get_depth__(self):
return lldb.eSearchDepthCompUnit
+ def __callback__(self, sym_ctx):
+ Resolver.__callback__(self, sym_ctx)
+
class ResolverFuncDepth(Resolver):
def __get_depth__(self):
return lldb.eSearchDepthFunction
+ def __callback__(self, sym_ctx):
+ Resolver.__callback__(self, sym_ctx)
+
class ResolverBadDepth(Resolver):
def __get_depth__(self):
return lldb.kLastSearchDepthKind + 1
+
+ def __callback__(self, sym_ctx):
+ Resolver.__callback__(self, sym_ctx)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py
index f52f6f7..2332eff 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/deque/TestDataFormatterGenericDeque.py
@@ -3,9 +3,6 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-USE_LIBSTDCPP = "USE_LIBSTDCPP"
-USE_LIBCPP = "USE_LIBCPP"
-
class GenericDequeDataFormatterTestCase(TestBase):
def findVariable(self, name):
@@ -56,8 +53,7 @@ class GenericDequeDataFormatterTestCase(TestBase):
],
)
- def do_test(self, stdlib_type):
- self.build(dictionary={stdlib_type: "1"})
+ def do_test(self):
(_, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
self, "break here", lldb.SBFileSpec("main.cpp")
)
@@ -135,15 +131,22 @@ class GenericDequeDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
def test_libstdcpp(self):
- self.do_test(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
@add_test_categories(["libc++"])
def test_libcpp(self):
- self.do_test(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build()
+ self.do_test()
- def do_test_ref_and_ptr(self, stdlib_type: str):
+ def do_test_ref_and_ptr(self):
"""Test formatting of std::deque& and std::deque*"""
- self.build(dictionary={stdlib_type: "1"})
(self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(
self, "stop here", lldb.SBFileSpec("main.cpp", False)
)
@@ -157,8 +160,15 @@ class GenericDequeDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
def test_libstdcpp_ref_and_ptr(self):
- self.do_test_ref_and_ptr(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_ref_and_ptr()
@add_test_categories(["libc++"])
def test_libcpp_ref_and_ptr(self):
- self.do_test_ref_and_ptr(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_ref_and_ptr()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl_ref_and_ptr(self):
+ self.build()
+ self.do_test_ref_and_ptr()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
index 5851588..07d6c96 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/TestDataFormatterStdMap.py
@@ -21,7 +21,7 @@ class StdMapDataFormatterTestCase(TestBase):
]
return ValueCheck(children=pair_children)
- def do_test(self):
+ def do_test(self, *, supports_end_iter=False):
"""Test that that file and class static variables display correctly."""
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
@@ -143,6 +143,9 @@ class StdMapDataFormatterTestCase(TestBase):
ValueCheck(name="second", value="0"),
],
)
+ if supports_end_iter:
+ self.expect("frame variable it_end", substrs=["= end"])
+ self.expect("frame variable const_it_end", substrs=["= end"])
# check that MightHaveChildren() gets it right
self.assertTrue(
@@ -343,3 +346,9 @@ class StdMapDataFormatterTestCase(TestBase):
dictionary={"USE_LIBSTDCPP": 1, "CXXFLAGS_EXTRAS": "-D_GLIBCXX_DEBUG"}
)
self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build()
+ self.do_test(supports_end_iter=True)
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/main.cpp
index 91bdf0b..a626f17 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/map/main.cpp
@@ -26,6 +26,8 @@ int main() {
intint_map::iterator it = ii.begin();
intint_map::const_iterator const_it = ii.cbegin();
std::printf("%d %d\n", it->second, const_it->second);
+ intint_map::iterator it_end = ii.end();
+ intint_map::const_iterator const_it_end = ii.cend();
thefoo_rw(1); // Set break point at this line.
ii[2] = 0;
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
index 5c0e159..7ac7971 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multimap/TestDataFormatterGenericMultiMap.py
@@ -9,9 +9,6 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-USE_LIBSTDCPP = "USE_LIBSTDCPP"
-USE_LIBCPP = "USE_LIBCPP"
-
class GenericMultiMapDataFormatterTestCase(TestBase):
def setUp(self):
@@ -38,9 +35,8 @@ class GenericMultiMapDataFormatterTestCase(TestBase):
var_name, type=self.getVariableType(var_name), children=children
)
- def do_test_with_run_command(self, stdlib_type):
+ def do_test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
- self.build(dictionary={stdlib_type: "1"})
self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
bkpt = self.target().FindBreakpointByID(
@@ -331,9 +327,17 @@ class GenericMultiMapDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
@skipIf(compiler="clang", compiler_version=["<", "9.0"])
def test_with_run_command_libstdcpp(self):
- self.do_test_with_run_command(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_with_run_command()
@skipIf(compiler="clang", compiler_version=["<", "9.0"])
@add_test_categories(["libc++"])
def test_with_run_command_libcpp(self):
- self.do_test_with_run_command(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_with_run_command()
+
+ @add_test_categories(["msvcstl"])
+ def test_with_run_command_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build()
+ self.do_test_with_run_command()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
index 24ab4de..7e922fc 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/multiset/TestDataFormatterGenericMultiSet.py
@@ -8,9 +8,6 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-USE_LIBSTDCPP = "USE_LIBSTDCPP"
-USE_LIBCPP = "USE_LIBCPP"
-
class GenericMultiSetDataFormatterTestCase(TestBase):
def setUp(self):
@@ -37,9 +34,8 @@ class GenericMultiSetDataFormatterTestCase(TestBase):
var_name, type=self.getVariableType(var_name), children=children
)
- def do_test_with_run_command(self, stdlib_type):
+ def do_test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
- self.build(dictionary={stdlib_type: "1"})
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)
)
@@ -129,9 +125,8 @@ class GenericMultiSetDataFormatterTestCase(TestBase):
],
)
- def do_test_ref_and_ptr(self, stdlib_type):
+ def do_test_ref_and_ptr(self):
"""Test that the data formatters work on ref and ptr."""
- self.build(dictionary={stdlib_type: "1"})
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
self,
"Stop here to check by ref and ptr.",
@@ -145,16 +140,31 @@ class GenericMultiSetDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
def test_with_run_command_libstdcpp(self):
- self.do_test_with_run_command(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_with_run_command()
@add_test_categories(["libc++"])
def test_with_run_command_libcpp(self):
- self.do_test_with_run_command(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_with_run_command()
+
+ @add_test_categories(["msvcstl"])
+ def test_with_run_command_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build()
+ self.do_test_with_run_command()
@add_test_categories(["libstdcxx"])
def test_ref_and_ptr_libstdcpp(self):
- self.do_test_ref_and_ptr(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_ref_and_ptr()
@add_test_categories(["libc++"])
def test_ref_and_ptr_libcpp(self):
- self.do_test_ref_and_ptr(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_ref_and_ptr()
+
+ @add_test_categories(["msvcstl"])
+ def test_ref_and_ptr_msvcstl(self):
+ self.build()
+ self.do_test_ref_and_ptr()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
index d3d6ef55..1ac5e32 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/TestDataFormatterGenericSet.py
@@ -8,9 +8,6 @@ from lldbsuite.test.decorators import *
from lldbsuite.test.lldbtest import *
from lldbsuite.test import lldbutil
-USE_LIBSTDCPP = "USE_LIBSTDCPP"
-USE_LIBCPP = "USE_LIBCPP"
-
class GenericSetDataFormatterTestCase(TestBase):
def setUp(self):
@@ -37,9 +34,8 @@ class GenericSetDataFormatterTestCase(TestBase):
var_name, type=self.getVariableType(var_name), children=children
)
- def do_test_with_run_command(self, stdlib_type):
+ def do_test_with_run_command(self):
"""Test that that file and class static variables display correctly."""
- self.build(dictionary={stdlib_type: "1"})
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
self, "Set break point at this line.", lldb.SBFileSpec("main.cpp", False)
)
@@ -74,6 +70,7 @@ class GenericSetDataFormatterTestCase(TestBase):
"[5] = 5",
],
)
+
lldbutil.continue_to_breakpoint(process, bkpt)
self.check("ii", 7)
@@ -129,15 +126,22 @@ class GenericSetDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
def test_with_run_command_libstdcpp(self):
- self.do_test_with_run_command(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_with_run_command()
@add_test_categories(["libc++"])
def test_with_run_command_libcpp(self):
- self.do_test_with_run_command(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_with_run_command()
- def do_test_ref_and_ptr(self, stdlib_type):
+ @add_test_categories(["msvcstl"])
+ def test_with_run_command_msvcstl(self):
+ # No flags, because the "msvcstl" category checks that the MSVC STL is used by default.
+ self.build()
+ self.do_test_with_run_command()
+
+ def do_test_ref_and_ptr(self):
"""Test that the data formatters work on ref and ptr."""
- self.build(dictionary={stdlib_type: "1"})
(self.target, process, _, bkpt) = lldbutil.run_to_source_breakpoint(
self,
"Stop here to check by ref and ptr.",
@@ -152,8 +156,15 @@ class GenericSetDataFormatterTestCase(TestBase):
@add_test_categories(["libstdcxx"])
def test_ref_and_ptr_libstdcpp(self):
- self.do_test_ref_and_ptr(USE_LIBSTDCPP)
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test_ref_and_ptr()
@add_test_categories(["libc++"])
def test_ref_and_ptr_libcpp(self):
- self.do_test_ref_and_ptr(USE_LIBCPP)
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test_ref_and_ptr()
+
+ @add_test_categories(["msvcstl"])
+ def test_ref_and_ptr_msvcstl(self):
+ self.build()
+ self.do_test_ref_and_ptr()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp
index 314d1e7..b029421 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/set/main.cpp
@@ -27,8 +27,8 @@ int main() {
ii.insert(3);
ii.insert(4);
ii.insert(5);
- thefoo_rw(1); // Set break point at this line.
+ thefoo_rw(1); // Set break point at this line.
ii.insert(6);
thefoo_rw(1); // Set break point at this line.
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
index 8c053f0..1811418 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/TestDataFormatterStdStringView.py
@@ -78,9 +78,6 @@ class StdStringViewDataFormatterTestCase(TestBase):
"u32_string", type="std::u32string_view", summary='U"🍄🍅🍆🍌"'
)
self.expect_var_path("u32_empty", type="std::u32string_view", summary='U""')
- self.expect_var_path(
- "oops", type="std::string_view", summary='"Hellooo World\\n"'
- )
# GetSummary returns None so can't be checked by expect_var_path, so we
# use the str representation instead
@@ -163,3 +160,8 @@ class StdStringViewDataFormatterTestCase(TestBase):
def test_libcxx(self):
self.build(dictionary={"USE_LIBCPP": 1})
self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvcstl(self):
+ self.build()
+ self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp
index 1e164786b..e8781fb 100644
--- a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/string_view/main.cpp
@@ -95,7 +95,6 @@ int main() {
std::string_view *null_str = nullptr;
std::string hello = "Hellooo ";
- std::string_view oops = hello + "World\n";
q_source[0] = 'H'; // Set break point at this line.
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/Makefile b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/Makefile
new file mode 100644
index 0000000..4f79c0a
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/Makefile
@@ -0,0 +1,4 @@
+CXX_SOURCES := main.cpp
+CXXFLAGS_EXTRAS := -std=c++20
+
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
new file mode 100644
index 0000000..1e35a0f
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/TestDataFormatterStdU8StringView.py
@@ -0,0 +1,44 @@
+# coding=utf8
+"""
+Test std::u8string_view summary.
+"""
+
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class StdU8StringViewDataFormatterTestCase(TestBase):
+ def do_test(self):
+ lldbutil.run_to_source_breakpoint(
+ self, "Set break point at this line.", lldb.SBFileSpec("main.cpp")
+ )
+
+ self.expect(
+ "frame variable",
+ substrs=[
+ '(std::u8string_view) u8_string_small = u8"🍄"',
+ '(std::u8string_view) u8_string = u8"❤️👍📄📁😃🧑‍🌾"',
+ '(std::u8string_view) u8_empty = u8""',
+ '(std::u8string_view) u8_text = u8"ABCd"',
+ ],
+ )
+
+ @expectedFailureAll(bugnumber="No libc++ formatters for std::u8string_view yet.")
+ @add_test_categories(["libc++"])
+ def test_libcxx(self):
+ self.build(dictionary={"USE_LIBCPP": 1})
+ self.do_test()
+
+ @expectedFailureAll(bugnumber="No libstdc++ formatters for std::u8string_view yet.")
+ @add_test_categories(["libstdcxx"])
+ def test_libstdcxx(self):
+ self.build(dictionary={"USE_LIBSTDCPP": 1})
+ self.do_test()
+
+ @add_test_categories(["msvcstl"])
+ def test_msvc(self):
+ self.build()
+ self.do_test()
diff --git a/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/main.cpp b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/main.cpp
new file mode 100644
index 0000000..458e783
--- /dev/null
+++ b/lldb/test/API/functionalities/data-formatter/data-formatter-stl/generic/u8string_view/main.cpp
@@ -0,0 +1,12 @@
+#include <cstdio>
+#include <string_view>
+
+int main() {
+ std::u8string_view u8_string_small(u8"🍄");
+ std::u8string_view u8_string(u8"❤️👍📄📁😃🧑‍🌾");
+ std::u8string_view u8_empty(u8"");
+ std::u8string_view u8_text(u8"ABC");
+ u8_text = u8"ABCd";
+
+ std::puts("// Set break point at this line.");
+}
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
index 9a70f67..db5b5a0 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
@@ -692,6 +692,9 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
"0102030405060708" # t4
"0102030405060708" # t5
"0102030405060708" # t6
+ "6162636465666768" # pc
+ "0000C03F" # ft0
+ "e07a6147a8a40940" # ft1
)
def qXferRead(self, obj, annex, offset, length):
@@ -737,6 +740,10 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
<reg name="t6" bitsize="64" type="int"/>
<reg name="pc" bitsize="64" type="code_ptr"/>
</feature>
+ <feature name='org.gnu.gdb.riscv.fpu'>
+ <reg name='ft0' bitsize='32' type='ieee_single'/>
+ <reg name='ft1' bitsize='64' type='ieee_double'/>
+ </feature>
</target>""",
False,
)
@@ -799,6 +806,10 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
self.match("register read x29", ["t4 = 0x0807060504030201"])
self.match("register read x30", ["t5 = 0x0807060504030201"])
self.match("register read x31", ["t6 = 0x0807060504030201"])
+ self.match("register read pc", ["pc = 0x6867666564636261"])
+ # test FPU registers
+ self.match("register read ft0", ["ft0 = 1.5"])
+ self.match("register read ft1", ["ft1 = 3.2053990913985757"])
@skipIfXmlSupportMissing
@skipIfRemote
diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
index 733f40b..445f422 100644
--- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
+++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py
@@ -8,7 +8,6 @@ from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase
LLDB_INVALID_ADDRESS = lldb.LLDB_INVALID_ADDRESS
load_address = 0x400000000
-
def format_register_value(val):
"""
Encode each byte by two hex digits in little-endian order.
@@ -35,6 +34,8 @@ class MyResponder(MockGDBServerResponder):
def respond(self, packet):
if packet[0:13] == "qRegisterInfo":
return self.qRegisterInfo(packet[13:])
+ if packet.startswith("qWasmCallStack"):
+ return self.qWasmCallStack()
return MockGDBServerResponder.respond(self, packet)
def qSupported(self, client_supported):
@@ -47,7 +48,7 @@ class MyResponder(MockGDBServerResponder):
return ""
def qfThreadInfo(self):
- return "OK"
+ return "m1,"
def qRegisterInfo(self, index):
if index == 0:
@@ -61,7 +62,7 @@ class MyResponder(MockGDBServerResponder):
)
def haltReason(self):
- return "T05thread:1;"
+ return "T02thread:1;"
def readRegister(self, register):
return format_register_value(self.current_pc)
@@ -89,6 +90,10 @@ class MyResponder(MockGDBServerResponder):
file.close()
return result
+ def qWasmCallStack(self):
+ # Return two 64-bit addresses: 0x40000000000001B3, 0x40000000000001FE
+ return "b301000000000040fe01000000000040"
+
class TestWasm(GDBRemoteTestBase):
@skipIfAsan
@@ -104,7 +109,7 @@ class TestWasm(GDBRemoteTestBase):
self.server.responder = MyResponder(obj_path, "test_wasm")
target = self.dbg.CreateTarget("")
- process = self.connect(target)
+ process = self.connect(target, "wasm")
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
@@ -174,7 +179,7 @@ class TestWasm(GDBRemoteTestBase):
)
target = self.dbg.CreateTarget("")
- process = self.connect(target)
+ process = self.connect(target, "wasm")
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
@@ -230,7 +235,7 @@ class TestWasm(GDBRemoteTestBase):
self.server.responder = MyResponder(obj_path)
target = self.dbg.CreateTarget("")
- process = self.connect(target)
+ process = self.connect(target, "wasm")
lldbutil.expect_state_changes(
self, self.dbg.GetListener(), process, [lldb.eStateStopped]
)
@@ -272,3 +277,14 @@ class TestWasm(GDBRemoteTestBase):
self.assertEqual(
LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)
)
+
+ thread = process.GetThreadAtIndex(0)
+ self.assertTrue(thread.IsValid())
+
+ frame = thread.GetFrameAtIndex(0)
+ self.assertTrue(frame.IsValid())
+ self.assertEqual(frame.GetPC(), 0x40000000000001B3)
+
+ frame = thread.GetFrameAtIndex(1)
+ self.assertTrue(frame.IsValid())
+ self.assertEqual(frame.GetPC(), 0x40000000000001FE)
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
index bfdc822..825e1a4 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
+++ b/lldb/test/API/linux/aarch64/mte_core_file/TestAArch64LinuxMTEMemoryTagCoreFile.py
@@ -10,8 +10,8 @@ from lldbsuite.test.lldbtest import *
class AArch64LinuxMTEMemoryTagCoreFileTestCase(TestBase):
NO_DEBUG_INFO_TESTCASE = True
- MTE_BUF_ADDR = hex(0xFFFF82C74000)
- BUF_ADDR = hex(0xFFFF82C73000)
+ MTE_BUF_ADDR = hex(0xFFFFA733B000)
+ BUF_ADDR = hex(0xFFFFA733A000)
@skipIfLLVMTargetMissing("AArch64")
def test_mte_tag_core_file_memory_region(self):
@@ -215,7 +215,7 @@ class AArch64LinuxMTEMemoryTagCoreFileTestCase(TestBase):
self.expect(
"bt",
substrs=[
- "* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address=0xffff82c74010)"
+ "* thread #1, name = 'a.out.mte', stop reason = SIGSEGV: sync tag check fault (fault address=0xffffa733b010)"
],
)
@@ -231,12 +231,15 @@ class AArch64LinuxMTEMemoryTagCoreFileTestCase(TestBase):
self.runCmd("target create --core core.mte")
# The expected value is:
# * Allowed tags value of 0xFFFF, shifted up by 3 resulting in 0x7fff8.
+ # * Bit 19 set to 0, which means that store only checking is disabled.
# * Bit 1 set to enable synchronous tag faults.
# * Bit 0 set to enable the tagged address ABI.
expected = ["mte_ctrl = 0x000000000007fffb"]
if self.hasXMLSupport():
- expected.append("(TAGS = 65535, TCF = TCF_SYNC, TAGGED_ADDR_ENABLE = 1)")
+ expected.append(
+ "(STORE_ONLY = 0, TAGS = 65535, TCF = TCF_SYNC, TAGGED_ADDR_ENABLE = 1)"
+ )
self.expect("register read mte_ctrl", substrs=expected)
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.mte b/lldb/test/API/linux/aarch64/mte_core_file/core.mte
index 84a3266..188d06d 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/core.mte
+++ b/lldb/test/API/linux/aarch64/mte_core_file/core.mte
Binary files differ
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.nomte b/lldb/test/API/linux/aarch64/mte_core_file/core.nomte
index 201f288..454ff83 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/core.nomte
+++ b/lldb/test/API/linux/aarch64/mte_core_file/core.nomte
Binary files differ
diff --git a/lldb/test/API/linux/aarch64/mte_core_file/main.c b/lldb/test/API/linux/aarch64/mte_core_file/main.c
index 6537edd..5974594 100644
--- a/lldb/test/API/linux/aarch64/mte_core_file/main.c
+++ b/lldb/test/API/linux/aarch64/mte_core_file/main.c
@@ -23,7 +23,7 @@
int main(int argc, char const *argv[]) {
#ifdef NO_MTE
- *(char *)(0) = 0;
+ __builtin_trap();
#endif
if (prctl(PR_SET_TAGGED_ADDR_CTRL,
diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt
index 6449ac5..b786edc 100644
--- a/lldb/test/CMakeLists.txt
+++ b/lldb/test/CMakeLists.txt
@@ -132,6 +132,10 @@ if(TARGET lldb-framework)
add_lldb_test_dependency(lldb-framework)
endif()
+if (LLDB_CAN_USE_LLDB_RPC_SERVER)
+ add_lldb_test_dependency(lldb-rpc-generate-sources)
+endif()
+
# Add dependencies that are not exported targets when building standalone.
if(NOT LLDB_BUILT_STANDALONE)
add_lldb_test_dependency(
@@ -249,7 +253,8 @@ llvm_canonicalize_cmake_booleans(
LLDB_TEST_SHELL_DISABLE_REMOTE
LLDB_TOOL_LLDB_SERVER_BUILD
LLDB_USE_SYSTEM_DEBUGSERVER
- LLDB_IS_64_BITS)
+ LLDB_IS_64_BITS
+ LLDB_BUILD_LLDBRPC)
# Configure the individual test suites.
add_subdirectory(API)
diff --git a/lldb/test/Shell/RPC/Generator/Inputs/SBDummy.h b/lldb/test/Shell/RPC/Generator/Inputs/SBDummy.h
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Inputs/SBDummy.h
diff --git a/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test b/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test
new file mode 100644
index 0000000..15fcf8f
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/Tests/CheckRPCGenToolByproducts.test
@@ -0,0 +1,9 @@
+RUN: %lldb-rpc-gen --output-dir=%t %S/../Inputs/SBDummy.h
+
+RUN: ls %t | FileCheck %s
+
+# We're just making sure that the tool emits the class names,
+# methods and skipped methods file in the output directory.
+CHECK: SBAPI.def
+CHECK: SBClasses.def
+CHECK: SkippedMethods.txt
diff --git a/lldb/test/Shell/RPC/Generator/lit.local.cfg b/lldb/test/Shell/RPC/Generator/lit.local.cfg
new file mode 100644
index 0000000..db94947
--- /dev/null
+++ b/lldb/test/Shell/RPC/Generator/lit.local.cfg
@@ -0,0 +1,3 @@
+# All tests for the tool need lldb-rpc-gen to be built.
+if not config.lldb_has_lldbrpc:
+ config.unsupported = True
diff --git a/lldb/test/Shell/helper/toolchain.py b/lldb/test/Shell/helper/toolchain.py
index 42968128..728f634 100644
--- a/lldb/test/Shell/helper/toolchain.py
+++ b/lldb/test/Shell/helper/toolchain.py
@@ -156,6 +156,16 @@ def use_lldb_substitutions(config):
extra_args=["platform"],
unresolved="ignore",
),
+ ToolSubst(
+ "%lldb-rpc-gen",
+ command=FindTool("lldb-rpc-gen"),
+ # We need the LLDB build directory root to pass into the tool, not the test build root.
+ extra_args=[
+ "-p " + config.lldb_build_directory + "/..",
+ '--extra-arg="-resource-dir=' + config.clang_resource_dir + '"',
+ ],
+ unresolved="ignore",
+ ),
"lldb-test",
"lldb-dap",
ToolSubst(
diff --git a/lldb/test/Shell/lit.site.cfg.py.in b/lldb/test/Shell/lit.site.cfg.py.in
index 5be5359..beaa41e 100644
--- a/lldb/test/Shell/lit.site.cfg.py.in
+++ b/lldb/test/Shell/lit.site.cfg.py.in
@@ -33,6 +33,7 @@ config.lldb_build_directory = "@LLDB_TEST_BUILD_DIRECTORY@"
config.have_lldb_server = @LLDB_TOOL_LLDB_SERVER_BUILD@
config.lldb_system_debugserver = @LLDB_USE_SYSTEM_DEBUGSERVER@
config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@"
+config.lldb_has_lldbrpc = @LLDB_BUILD_LLDBRPC@
# The shell tests use their own module caches.
config.lldb_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_LLDB@", "lldb-shell")
config.clang_module_cache = os.path.join("@LLDB_TEST_MODULE_CACHE_CLANG@", "lldb-shell")
diff --git a/lldb/tools/CMakeLists.txt b/lldb/tools/CMakeLists.txt
index 6804dc2..e2f0395 100644
--- a/lldb/tools/CMakeLists.txt
+++ b/lldb/tools/CMakeLists.txt
@@ -10,6 +10,12 @@ add_subdirectory(lldb-fuzzer EXCLUDE_FROM_ALL)
add_lldb_tool_subdirectory(lldb-instr)
add_lldb_tool_subdirectory(lldb-dap)
+if (LLDB_BUILD_LLDBRPC)
+ add_lldb_tool_subdirectory(lldb-rpc-gen)
+endif()
+if (LLDB_CAN_USE_LLDB_RPC_SERVER)
+ add_subdirectory(lldb-rpc)
+endif()
if (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_lldb_tool_subdirectory(darwin-debug)
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 8be384c..102b2ab 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -21,6 +21,7 @@
#include <mach/exception_types.h>
#include <mach/mach_vm.h>
#include <mach/task_info.h>
+#include <memory>
#include <pwd.h>
#include <string>
#include <sys/stat.h>
@@ -5410,9 +5411,8 @@ RNBRemote::GetJSONThreadsInfo(bool threads_with_valid_stop_info_only) {
JSONGenerator::ArraySP medata_array_sp(new JSONGenerator::Array());
for (nub_size_t i = 0;
i < tid_stop_info.details.exception.data_count; ++i) {
- medata_array_sp->AddItem(
- JSONGenerator::IntegerSP(new JSONGenerator::Integer(
- tid_stop_info.details.exception.data[i])));
+ medata_array_sp->AddItem(std::make_shared<JSONGenerator::Integer>(
+ tid_stop_info.details.exception.data[i]));
}
thread_dict_sp->AddItem("medata", medata_array_sp);
}
diff --git a/lldb/tools/lldb-rpc-gen/CMakeLists.txt b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
new file mode 100644
index 0000000..65b7643
--- /dev/null
+++ b/lldb/tools/lldb-rpc-gen/CMakeLists.txt
@@ -0,0 +1,23 @@
+add_lldb_tool(lldb-rpc-gen
+ RPCCommon.cpp
+ server/RPCServerHeaderEmitter.cpp
+ server/RPCServerSourceEmitter.cpp
+ lldb-rpc-gen.cpp
+
+ CLANG_LIBS
+ clangAST
+ clangBasic
+ clangCodeGen
+ clangFrontend
+ clangLex
+ clangRewrite
+ clangSerialization
+ clangTooling
+
+ LINK_COMPONENTS
+ Support
+ )
+
+if (NOT DEFINED LLDB_RPC_GEN_EXE)
+ set(LLDB_RPC_GEN_EXE $<TARGET_FILE:lldb-rpc-gen> CACHE STRING "Executable that generates lldb-rpc-server")
+endif()
diff --git a/lldb/tools/lldb-rpc-gen/RPCCommon.cpp b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp
new file mode 100644
index 0000000..7af6ee3
--- /dev/null
+++ b/lldb/tools/lldb-rpc-gen/RPCCommon.cpp
@@ -0,0 +1,493 @@
+//===-- RPCCommon.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 "RPCCommon.h"
+
+#include "clang/AST/AST.h"
+#include "clang/AST/Attr.h"
+#include "clang/AST/DeclBase.h"
+#include "clang/AST/Mangle.h"
+#include "clang/Lex/Lexer.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <cstring>
+
+using namespace clang;
+
+// We intentionally do not generate some classes because they are currently
+// inconvenient, they aren't really used by most consumers, or we're not sure
+// why they exist.
+static constexpr llvm::StringRef DisallowedClasses[] = {
+ "SBCommunication", // This class is pretty much unused by consumers, so we
+ // skip it.
+ "SBInputReader", // This class is pretty much unused by consumers, so we
+ // skip it.
+ "SBCommandPluginInterface", // This class uses virtual functions, and the SB
+ // API should not have those, so we skip this
+ // class.
+ "SBCommand", // There's nothing too difficult about this one, but many of
+ // its methods take a SBCommandPluginInterface pointer so
+ // there's no reason to support this.
+};
+
+// NOTE: In lldb-rpc-gen, we use mangled names when we need to work with
+// functions. We do this because we support many functions that have overloads,
+// and mangled names have no ambiguity which makes it easier to keep track of.
+// This is also possible since the LLDB SB API is stable.
+
+// We intentionally avoid generating certain methods either because they are
+// difficult to support correctly or they aren't really used much from C++.
+// NOTE: These methods are marked as deprecated using LLDB_DEPRECATED.
+// Normally this macro defines to the deprecated annotation, but this
+// functionality is removed in SBDefines.h when generating SWIG bindings which
+// we use for testing. Because of this, there is no annotation for the tool to
+// pick up on so this list will be used while we have this restriction in
+// SBDefines.h.
+static constexpr llvm::StringRef DisallowedMethods[] = {
+ // The threading functionality in SBHostOS is deprecated and thus we do not
+ // generate them. It would be ideal to add the annotations to the methods
+ // and then support not generating deprecated methods. However, without
+ // annotations the generator generates most things correctly. This one is
+ // problematic because it returns a pointer to an "opaque" structure
+ // (thread_t) that is not `void *`, so special casing it is more effort than
+ // it's worth.
+ "_ZN4lldb8SBHostOS10ThreadJoinEP17_opaque_pthread_tPPvPNS_7SBErrorE",
+ "_ZN4lldb8SBHostOS12ThreadCancelEP17_opaque_pthread_tPNS_7SBErrorE",
+ "_ZN4lldb8SBHostOS12ThreadCreateEPKcPFPvS3_ES3_PNS_7SBErrorE",
+ "_ZN4lldb8SBHostOS12ThreadDetachEP17_opaque_pthread_tPNS_7SBErrorE",
+ "_ZN4lldb8SBHostOS13ThreadCreatedEPKc",
+};
+
+static constexpr llvm::StringRef ClassesWithoutDefaultCtor[] = {
+ "SBHostOS",
+ "SBReproducer",
+};
+
+static constexpr llvm::StringRef ClassesWithoutCopyOperations[] = {
+ "SBHostOS",
+ "SBReproducer",
+ "SBStream",
+ "SBProgress",
+};
+
+static constexpr llvm::StringRef MethodsWithPointerPlusLen[] = {
+ "_ZN4lldb6SBData11ReadRawDataERNS_7SBErrorEyPvm",
+ "_ZN4lldb6SBData7SetDataERNS_7SBErrorEPKvmNS_9ByteOrderEh",
+ "_ZN4lldb6SBData20SetDataWithOwnershipERNS_7SBErrorEPKvmNS_9ByteOrderEh",
+ "_ZN4lldb6SBData25CreateDataFromUInt64ArrayENS_9ByteOrderEjPym",
+ "_ZN4lldb6SBData25CreateDataFromUInt32ArrayENS_9ByteOrderEjPjm",
+ "_ZN4lldb6SBData25CreateDataFromSInt64ArrayENS_9ByteOrderEjPxm",
+ "_ZN4lldb6SBData25CreateDataFromSInt32ArrayENS_9ByteOrderEjPim",
+ "_ZN4lldb6SBData25CreateDataFromDoubleArrayENS_9ByteOrderEjPdm",
+ "_ZN4lldb6SBData22SetDataFromUInt64ArrayEPym",
+ "_ZN4lldb6SBData22SetDataFromUInt32ArrayEPjm",
+ "_ZN4lldb6SBData22SetDataFromSInt64ArrayEPxm",
+ "_ZN4lldb6SBData22SetDataFromSInt32ArrayEPim",
+ "_ZN4lldb6SBData22SetDataFromDoubleArrayEPdm",
+ "_ZN4lldb10SBDebugger22GetDefaultArchitectureEPcm",
+ "_ZN4lldb10SBDebugger13DispatchInputEPvPKvm",
+ "_ZN4lldb10SBDebugger13DispatchInputEPKvm",
+ "_ZN4lldb6SBFile4ReadEPhmPm",
+ "_ZN4lldb6SBFile5WriteEPKhmPm",
+ "_ZNK4lldb10SBFileSpec7GetPathEPcm",
+ "_ZN4lldb10SBFileSpec11ResolvePathEPKcPcm",
+ "_ZN4lldb8SBModule10GetVersionEPjj",
+ "_ZN4lldb12SBModuleSpec12SetUUIDBytesEPKhm",
+ "_ZNK4lldb9SBProcess9GetSTDOUTEPcm",
+ "_ZNK4lldb9SBProcess9GetSTDERREPcm",
+ "_ZNK4lldb9SBProcess19GetAsyncProfileDataEPcm",
+ "_ZN4lldb9SBProcess10ReadMemoryEyPvmRNS_7SBErrorE",
+ "_ZN4lldb9SBProcess11WriteMemoryEyPKvmRNS_7SBErrorE",
+ "_ZN4lldb9SBProcess21ReadCStringFromMemoryEyPvmRNS_7SBErrorE",
+ "_ZNK4lldb16SBStructuredData14GetStringValueEPcm",
+ "_ZN4lldb8SBTarget23BreakpointCreateByNamesEPPKcjjRKNS_"
+ "14SBFileSpecListES6_",
+ "_ZN4lldb8SBTarget10ReadMemoryENS_9SBAddressEPvmRNS_7SBErrorE",
+ "_ZN4lldb8SBTarget15GetInstructionsENS_9SBAddressEPKvm",
+ "_ZN4lldb8SBTarget25GetInstructionsWithFlavorENS_9SBAddressEPKcPKvm",
+ "_ZN4lldb8SBTarget15GetInstructionsEyPKvm",
+ "_ZN4lldb8SBTarget25GetInstructionsWithFlavorEyPKcPKvm",
+ "_ZN4lldb8SBThread18GetStopDescriptionEPcm",
+ // The below mangled names are used for dummy methods in shell tests
+ // that test the emitters' output. If you're adding any new mangled names
+ // from the actual SB API to this list please add them above.
+ "_ZN4lldb33SBRPC_"
+ "CHECKCONSTCHARPTRPTRWITHLEN27CheckConstCharPtrPtrWithLenEPPKcm",
+ "_ZN4lldb19SBRPC_CHECKARRAYPTR13CheckArrayPtrEPPKcm",
+ "_ZN4lldb18SBRPC_CHECKVOIDPTR12CheckVoidPtrEPvm",
+};
+
+// These classes inherit from rpc::ObjectRef directly (as opposed to
+// rpc::LocalObjectRef). Changing them from ObjectRef to LocalObjectRef is ABI
+// breaking, so we preserve that compatibility here.
+//
+// lldb-rpc-gen emits classes as LocalObjectRefs by default.
+//
+// FIXME: Does it matter which one it emits by default?
+static constexpr llvm::StringRef ClassesThatInheritFromObjectRef[] = {
+ "SBAddress",
+ "SBBreakpointName",
+ "SBCommandInterpreter",
+ "SBCommandReturnObject",
+ "SBError",
+ "SBExecutionContext",
+ "SBExpressionOptions",
+ "SBFileSpec",
+ "SBFileSpecList",
+ "SBFormat",
+ "SBFunction",
+ "SBHistoricalFrame",
+ "SBHistoricalLineEntry",
+ "SBHistoricalLineEntryList",
+ "SBLineEntry",
+ "SBStream",
+ "SBStringList",
+ "SBStructuredData",
+ "SBSymbolContext",
+ "SBSymbolContextList",
+ "SBTypeMember",
+ "SBTypeSummaryOptions",
+ "SBValueList",
+};
+
+QualType lldb_rpc_gen::GetUnderlyingType(QualType T) {
+ QualType UnderlyingType;
+ if (T->isPointerType())
+ UnderlyingType = T->getPointeeType();
+ else if (T->isReferenceType())
+ UnderlyingType = T.getNonReferenceType();
+ else
+ UnderlyingType = T;
+
+ return UnderlyingType;
+}
+
+QualType lldb_rpc_gen::GetUnqualifiedUnderlyingType(QualType T) {
+ return GetUnderlyingType(T).getUnqualifiedType();
+}
+
+std::string lldb_rpc_gen::GetMangledName(ASTContext &Context,
+ CXXMethodDecl *MDecl) {
+ std::string Mangled;
+ llvm::raw_string_ostream MangledStream(Mangled);
+
+ GlobalDecl GDecl;
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(MDecl))
+ GDecl = GlobalDecl(CtorDecl, Ctor_Complete);
+ else if (const auto *DtorDecl = dyn_cast<CXXDestructorDecl>(MDecl))
+ GDecl = GlobalDecl(DtorDecl, Dtor_Deleting);
+ else
+ GDecl = GlobalDecl(MDecl);
+
+ MangleContext *MC = Context.createMangleContext();
+ MC->mangleName(GDecl, MangledStream);
+ return Mangled;
+}
+
+bool lldb_rpc_gen::TypeIsFromLLDBPrivate(QualType T) {
+ auto CheckTypeForLLDBPrivate = [](const Type *Ty) {
+ if (!Ty)
+ return false;
+ const auto *CXXRDecl = Ty->getAsCXXRecordDecl();
+ if (!CXXRDecl)
+ return false;
+ const auto *NSDecl =
+ llvm::dyn_cast<NamespaceDecl>(CXXRDecl->getDeclContext());
+ if (!NSDecl)
+ return false;
+ return NSDecl->getName() == "lldb_private";
+ };
+
+ // First, get the underlying type (remove qualifications and strip off any
+ // pointers/references). Then we'll need to desugar this type. This will
+ // remove things like typedefs, so instead of seeing "lldb::DebuggerSP" we'll
+ // actually see something like "std::shared_ptr<lldb_private::Debugger>".
+ QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
+ const Type *DesugaredType =
+ UnqualifiedUnderlyingType->getUnqualifiedDesugaredType();
+ assert(DesugaredType && "DesugaredType from a valid Type is nullptr!");
+
+ // Check the type itself.
+ if (CheckTypeForLLDBPrivate(DesugaredType))
+ return true;
+
+ // If that didn't work, it's possible that the type has a template argument
+ // that is an lldb_private type.
+ if (const auto *TemplateSDecl =
+ llvm::dyn_cast_or_null<ClassTemplateSpecializationDecl>(
+ DesugaredType->getAsCXXRecordDecl())) {
+ for (const TemplateArgument &TA :
+ TemplateSDecl->getTemplateArgs().asArray()) {
+ if (TA.getKind() != TemplateArgument::Type)
+ continue;
+ if (CheckTypeForLLDBPrivate(TA.getAsType().getTypePtr()))
+ return true;
+ }
+ }
+ return false;
+}
+
+bool lldb_rpc_gen::TypeIsSBClass(QualType T) {
+ QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
+ const auto *CXXRDecl = UnqualifiedUnderlyingType->getAsCXXRecordDecl();
+ if (!CXXRDecl)
+ return false; // SB Classes are always C++ classes
+
+ return CXXRDecl->getName().starts_with("SB");
+}
+
+bool lldb_rpc_gen::TypeIsConstCharPtr(QualType T) {
+ if (!T->isPointerType())
+ return false;
+
+ QualType UnderlyingType = T->getPointeeType();
+ if (!UnderlyingType.isConstQualified())
+ return false;
+
+ // NOTE: We should be able to do `UnderlyingType->isCharType` but that will
+ // return true for `const uint8_t *` since that is effectively an unsigned
+ // char pointer. We currently do not support pointers other than `const char
+ // *` and `const char **`.
+
+ // NOTE: Checking that the underlying type is a signed integer works on Darwin
+ // platforms, but Linux platforms expect that the underlying type is an
+ // unsigned integer.
+ return UnderlyingType->isSpecificBuiltinType(BuiltinType::Char_S) ||
+ UnderlyingType->isSpecificBuiltinType(BuiltinType::SChar) ||
+ UnderlyingType->isSpecificBuiltinType(BuiltinType::Char_U) ||
+ UnderlyingType->isSpecificBuiltinType(BuiltinType::UChar);
+}
+
+bool lldb_rpc_gen::TypeIsConstCharPtrPtr(QualType T) {
+ if (!T->isPointerType())
+ return false;
+
+ return TypeIsConstCharPtr(T->getPointeeType());
+}
+
+bool lldb_rpc_gen::TypeIsDisallowedClass(QualType T) {
+ QualType UUT = GetUnqualifiedUnderlyingType(T);
+ const auto *CXXRDecl = UUT->getAsCXXRecordDecl();
+ if (!CXXRDecl)
+ return false;
+
+ llvm::StringRef DeclName = CXXRDecl->getName();
+ for (const llvm::StringRef DisallowedClass : DisallowedClasses)
+ if (DeclName == DisallowedClass)
+ return true;
+ return false;
+}
+
+bool lldb_rpc_gen::TypeIsCallbackFunctionPointer(QualType T) {
+ return T->isFunctionPointerType();
+}
+
+bool lldb_rpc_gen::MethodIsDisallowed(ASTContext &Context,
+ CXXMethodDecl *MDecl) {
+ bool isDisallowed = false;
+ std::string MangledName = lldb_rpc_gen::GetMangledName(Context, MDecl);
+ if (llvm::is_contained(DisallowedMethods, MangledName))
+ isDisallowed = true;
+
+ if (MDecl->hasAttrs()) {
+ for (auto *attr : MDecl->getAttrs()) {
+ if (strcmp(attr->getAttrName()->getNameStart(), "deprecated") == 0)
+ isDisallowed = true;
+ }
+ }
+ return isDisallowed;
+}
+
+// NOTE: There's possibly a more clever way to do this, but we're keeping
+// the string replacement way here. Here is why it is written this way:
+// By the time we have already created a `Method` object, we have extracted the
+// `QualifiedName` and the relevant QualTypes for parameters/return types, many
+// of which contains "lldb::" in them. To change it in a way that would be
+// friendly to liblldbrpc, we would need to have a way of replacing that
+// namespace at the time of creating a Method, and only for liblldbrpc methods.
+// IMO this would complicate Method more than what I'm doing here, and not
+// necessarily for any more benefit.
+// In clang-tools-extra, there is a ChangeNamespaces tool which tries to do
+// something similar to this. It also operates primarily on string replacement,
+// but uses more sophisticated clang tooling to do so.
+// For now, this will do what we need it to do.
+std::string
+lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(std::string Name) {
+ const char *lldb_namespace = "lldb::";
+ auto Pos = Name.find(lldb_namespace);
+ while (Pos != std::string::npos) {
+ constexpr size_t SizeOfLLDBNamespace = 6;
+ Name.replace(Pos, SizeOfLLDBNamespace, "lldb_rpc::");
+ Pos = Name.find(lldb_namespace);
+ }
+ return Name;
+}
+
+std::string lldb_rpc_gen::StripLLDBNamespace(std::string Name) {
+ const char *lldb_namespace = "lldb::";
+ auto Pos = Name.find(lldb_namespace);
+ if (Pos != std::string::npos) {
+ constexpr size_t SizeOfLLDBNamespace = 6;
+ Name = Name.substr(Pos + SizeOfLLDBNamespace);
+ }
+ return Name;
+}
+
+bool lldb_rpc_gen::SBClassRequiresDefaultCtor(const std::string &ClassName) {
+ return !llvm::is_contained(ClassesWithoutDefaultCtor, ClassName);
+}
+
+bool lldb_rpc_gen::SBClassRequiresCopyCtorAssign(const std::string &ClassName) {
+ return !llvm::is_contained(ClassesWithoutCopyOperations, ClassName);
+}
+
+bool lldb_rpc_gen::SBClassInheritsFromObjectRef(const std::string &ClassName) {
+ return llvm::is_contained(ClassesThatInheritFromObjectRef, ClassName);
+}
+
+std::string lldb_rpc_gen::GetSBClassNameFromType(QualType T) {
+ assert(lldb_rpc_gen::TypeIsSBClass(T) &&
+ "Cannot get SBClass name from non-SB class type!");
+
+ QualType UnqualifiedUnderlyingType = GetUnqualifiedUnderlyingType(T);
+ const auto *CXXRDecl = UnqualifiedUnderlyingType->getAsCXXRecordDecl();
+ assert(CXXRDecl && "SB class was not CXXRecordDecl!");
+ if (!CXXRDecl)
+ return std::string();
+
+ return CXXRDecl->getName().str();
+}
+lldb_rpc_gen::Method::Method(CXXMethodDecl *MDecl, const PrintingPolicy &Policy,
+ ASTContext &Context)
+ : Policy(Policy), Context(Context),
+ QualifiedName(MDecl->getQualifiedNameAsString()),
+ BaseName(MDecl->getNameAsString()),
+ MangledName(lldb_rpc_gen::GetMangledName(Context, MDecl)),
+ ReturnType(MDecl->getReturnType()), IsConst(MDecl->isConst()),
+ IsInstance(MDecl->isInstance()), IsCtor(isa<CXXConstructorDecl>(MDecl)),
+ IsCopyAssign(MDecl->isCopyAssignmentOperator()),
+ IsMoveAssign(MDecl->isMoveAssignmentOperator()),
+ IsDtor(isa<CXXDestructorDecl>(MDecl)),
+ IsConversionMethod(isa<CXXConversionDecl>(MDecl)) {
+ uint8_t UnnamedArgIdx = 0;
+ bool PrevParamWasPointer = false;
+ for (const auto *ParamDecl : MDecl->parameters()) {
+ Param param;
+ if (ParamDecl->hasDefaultArg())
+ param.DefaultValueText =
+ Lexer::getSourceText(
+ CharSourceRange::getTokenRange(
+ ParamDecl->getDefaultArg()->getSourceRange()),
+ Context.getSourceManager(), Context.getLangOpts())
+ .str();
+
+ param.IsFollowedByLen = false;
+ param.Name = ParamDecl->getNameAsString();
+ // If the parameter has no name, we'll generate one
+ if (param.Name.empty()) {
+ param.Name = "arg" + std::to_string(UnnamedArgIdx);
+ UnnamedArgIdx++;
+ }
+ param.Type = ParamDecl->getType();
+
+ // FIXME: Instead of using this heuristic, the ideal thing would be to add
+ // annotations to the SBAPI methods themselves. For now, we have a list of
+ // methods that we know will need this.
+ if (PrevParamWasPointer) {
+ PrevParamWasPointer = false;
+ const bool IsIntegerType = param.Type->isIntegerType() &&
+ !param.Type->isBooleanType() &&
+ !param.Type->isEnumeralType();
+ if (IsIntegerType && llvm::is_contained(MethodsWithPointerPlusLen,
+ llvm::StringRef(MangledName)))
+ Params.back().IsFollowedByLen = true;
+ }
+
+ if (param.Type->isPointerType() &&
+ !lldb_rpc_gen::TypeIsConstCharPtr(param.Type) &&
+ !param.Type->isFunctionPointerType())
+ PrevParamWasPointer = true;
+
+ if (param.Type->isFunctionPointerType())
+ ContainsFunctionPointerParameter = true;
+
+ Params.push_back(param);
+ }
+
+ if (IsInstance)
+ ThisType = MDecl->getThisType();
+
+ if (const auto *CtorDecl = dyn_cast<CXXConstructorDecl>(MDecl)) {
+ IsExplicitCtorOrConversionMethod = CtorDecl->isExplicit();
+ IsCopyCtor = CtorDecl->isCopyConstructor();
+ IsMoveCtor = CtorDecl->isMoveConstructor();
+ } else if (const auto *ConversionDecl = dyn_cast<CXXConversionDecl>(MDecl))
+ IsExplicitCtorOrConversionMethod = ConversionDecl->isExplicit();
+}
+
+// Adding a '<' allows us to use Methods in ordered containers.
+// The ordering is on memory addresses.
+bool lldb_rpc_gen::Method::operator<(const lldb_rpc_gen::Method &rhs) const {
+ return this < &rhs;
+}
+
+std::string
+lldb_rpc_gen::Method::CreateParamListAsString(GenerationKind Generation,
+ bool IncludeDefaultValue) const {
+ assert((!IncludeDefaultValue || Generation == eLibrary) &&
+ "Default values should only be emitted on the library side!");
+
+ std::vector<std::string> ParamList;
+
+ if (Generation == eLibrary && RequiresConnectionParameter())
+ ParamList.push_back("const rpc::Connection &connection");
+
+ for (const auto &Param : Params) {
+ std::string ParamString;
+ llvm::raw_string_ostream ParamStringStream(ParamString);
+
+ if (Generation == eLibrary)
+ ParamStringStream << lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
+ Param.Type.getAsString(Policy));
+ else
+ ParamStringStream << Param.Type.getAsString(Policy);
+
+ ParamStringStream << " " << Param.Name;
+ if (IncludeDefaultValue && Generation == eLibrary &&
+ !Param.DefaultValueText.empty())
+ ParamStringStream << " = "
+ << lldb_rpc_gen::ReplaceLLDBNamespaceWithRPCNamespace(
+ Param.DefaultValueText);
+
+ ParamList.push_back(ParamString);
+ }
+
+ return llvm::join(ParamList, ", ");
+}
+
+bool lldb_rpc_gen::Method::RequiresConnectionParameter() const {
+ if (!IsCtor && IsInstance)
+ return false;
+ if (IsCopyCtor || IsMoveCtor)
+ return false;
+ for (const auto &Param : Params) {
+ // We can re-use the connection from our parameter if possible.
+ // Const-qualified parameters are input parameters and already
+ // have a valid connection to provide to the current method.
+ if (TypeIsSBClass(Param.Type) &&
+ GetUnderlyingType(Param.Type).isConstQualified())
+ return false;
+ }
+
+ return true;
+}
diff --git a/lldb/tools/lldb-rpc-gen/RPCCommon.h b/lldb/tools/lldb-rpc-gen/RPCCommon.h
new file mode 100644
index 0000000..2a309d0
--- /dev/null
+++ b/lldb/tools/lldb-rpc-gen/RPCCommon.h
@@ -0,0 +1,107 @@
+//===-- RPCCommon.h -------------------------------------------------------===//
+//
+// 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_RPC_GEN_RPCCOMMON_H
+#define LLDB_RPC_GEN_RPCCOMMON_H
+
+#include "clang/AST/AST.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/DeclCXX.h"
+#include "llvm/Support/ToolOutputFile.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <string>
+
+using namespace clang;
+
+namespace lldb_rpc_gen {
+QualType GetUnderlyingType(QualType T);
+QualType GetUnqualifiedUnderlyingType(QualType T);
+std::string GetMangledName(ASTContext &Context, CXXMethodDecl *MDecl);
+
+bool TypeIsFromLLDBPrivate(QualType T);
+bool TypeIsSBClass(QualType T);
+bool TypeIsConstCharPtr(QualType T);
+bool TypeIsConstCharPtrPtr(QualType T);
+bool TypeIsDisallowedClass(QualType T);
+bool TypeIsCallbackFunctionPointer(QualType T);
+
+bool MethodIsDisallowed(ASTContext &Context, CXXMethodDecl *MDecl);
+
+std::string ReplaceLLDBNamespaceWithRPCNamespace(std::string Name);
+std::string StripLLDBNamespace(std::string Name);
+bool SBClassRequiresDefaultCtor(const std::string &ClassName);
+bool SBClassRequiresCopyCtorAssign(const std::string &ClassName);
+bool SBClassInheritsFromObjectRef(const std::string &ClassName);
+std::string GetSBClassNameFromType(QualType T);
+struct Param {
+ std::string Name;
+ QualType Type;
+ std::string DefaultValueText;
+ bool IsFollowedByLen;
+};
+
+enum GenerationKind : bool { eServer, eLibrary };
+
+struct Method {
+ enum Type { eOther, eConstructor, eDestructor };
+
+ Method(CXXMethodDecl *MDecl, const PrintingPolicy &Policy,
+ ASTContext &Context);
+
+ // Adding a '<' allows us to use Methods in ordered containers.
+ // The ordering is on memory addresses.
+ bool operator<(const lldb_rpc_gen::Method &rhs) const;
+ const PrintingPolicy &Policy;
+ const ASTContext &Context;
+ std::string QualifiedName;
+ std::string BaseName;
+ std::string MangledName;
+ QualType ReturnType;
+ QualType ThisType;
+ std::vector<Param> Params;
+ bool IsConst = false;
+ bool IsInstance = false;
+ bool IsCtor = false;
+ bool IsCopyCtor = false;
+ bool IsCopyAssign = false;
+ bool IsMoveCtor = false;
+ bool IsMoveAssign = false;
+ bool IsDtor = false;
+ bool IsConversionMethod = false;
+ bool IsExplicitCtorOrConversionMethod = false;
+ bool ContainsFunctionPointerParameter = false;
+
+ std::string CreateParamListAsString(GenerationKind Generation,
+ bool IncludeDefaultValue = false) const;
+
+ bool RequiresConnectionParameter() const;
+};
+
+std::string
+GetDefaultArgumentsForConstructor(std::string ClassName,
+ const lldb_rpc_gen::Method &method);
+
+class FileEmitter {
+protected:
+ FileEmitter(std::unique_ptr<llvm::ToolOutputFile> &&OutputFile)
+ : OutputFile(std::move(OutputFile)), IndentLevel(0) {}
+ void EmitLine(const std::string &line) {
+ for (auto i = 0; i < IndentLevel; i++)
+ OutputFile->os() << " ";
+
+ OutputFile->os() << line << "\n";
+ }
+
+ void EmitNewLine() { OutputFile->os() << "\n"; }
+
+ std::unique_ptr<llvm::ToolOutputFile> OutputFile;
+ uint8_t IndentLevel;
+};
+} // namespace lldb_rpc_gen
+#endif // LLDB_RPC_GEN_RPCCOMMON_H
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp b/lldb/tools/lldb-rpc-gen/lldb-rpc-gen.cpp
index e6b601e..9b48796 100644
--- a/lldb/tools/lldb-rpc/lldb-rpc-gen/lldb-rpc-gen.cpp
+++ b/lldb/tools/lldb-rpc-gen/lldb-rpc-gen.cpp
@@ -7,8 +7,8 @@
//===----------------------------------------------------------------------===//
#include "RPCCommon.h"
-#include "RPCServerHeaderEmitter.h"
-#include "RPCServerSourceEmitter.h"
+#include "server/RPCServerHeaderEmitter.h"
+#include "server/RPCServerSourceEmitter.h"
#include "clang/AST/AST.h"
#include "clang/AST/ASTConsumer.h"
@@ -40,15 +40,15 @@ static llvm::cl::opt<std::string>
llvm::cl::desc("Directory to output generated files to"),
llvm::cl::init(""), llvm::cl::cat(RPCGenCategory));
-static std::string GetLibraryOutputDirectory() {
+static std::string GetServerOutputDirectory() {
llvm::SmallString<128> Path(OutputDir.getValue());
- llvm::sys::path::append(Path, "lib");
+ llvm::sys::path::append(Path, "server");
return std::string(Path);
}
static std::unique_ptr<llvm::ToolOutputFile>
CreateOutputFile(llvm::StringRef OutputDir, llvm::StringRef Filename) {
- llvm::SmallString<128> Path(OutputDir);
+ llvm::SmallString<256> Path(OutputDir);
llvm::sys::path::append(Path, Filename);
std::error_code EC;
@@ -100,9 +100,8 @@ public:
for (CXXMethodDecl *MDecl : RDecl->methods()) {
const std::string MangledName =
lldb_rpc_gen::GetMangledName(Context, MDecl);
- const bool IsDisallowed = lldb_rpc_gen::MethodIsDisallowed(MangledName);
- const bool HasCallbackParameter =
- lldb_rpc_gen::HasCallbackParameter(MDecl);
+ const bool IsDisallowed =
+ lldb_rpc_gen::MethodIsDisallowed(Context, MDecl);
SupportLevel MethodSupportLevel = GetMethodSupportLevel(MDecl);
if (MethodSupportLevel == eImplemented && !IsDisallowed) {
const lldb_rpc_gen::Method Method(MDecl, Policy, Context);
@@ -314,9 +313,9 @@ bool EmitClassNamesFile(std::set<std::string> &ClassNames) {
if (!ClassNamesFile)
return false;
- ClassNamesFile->os() << "#ifndef SBCLASS\n";
- ClassNamesFile->os() << "#error \"SBClass must be defined\"\n";
- ClassNamesFile->os() << "#endif\n";
+ ClassNamesFile->os() << "#ifndef SBCLASS\n"
+ << "#error \"SBClass must be defined\"\n"
+ << "#endif\n";
for (const auto &ClassName : ClassNames) {
if (ClassName == "SBStream" || ClassName == "SBProgress")
@@ -340,9 +339,9 @@ bool EmitMethodNamesFile(std::set<std::string> &MangledMethodNames) {
if (!MethodNamesFile)
return false;
- MethodNamesFile->os() << "#ifndef GENERATE_SBAPI\n";
- MethodNamesFile->os() << "#error \"GENERATE_SBAPI must be defined\"\n";
- MethodNamesFile->os() << "#endif\n";
+ MethodNamesFile->os() << "#ifndef GENERATE_SBAPI\n"
+ << "#error \"GENERATE_SBAPI must be defined\"\n"
+ << "#endif\n";
for (const auto &MangledName : MangledMethodNames) {
MethodNamesFile->os() << "GENERATE_SBAPI(" << MangledName << ")\n";
@@ -358,9 +357,8 @@ bool EmitSkippedMethodsFile(std::set<std::string> &SkippedMethodNames) {
if (!File)
return false;
- for (const auto &Skipped : SkippedMethodNames) {
+ for (const auto &Skipped : SkippedMethodNames)
File->os() << Skipped << "\n";
- }
File->keep();
return true;
}
@@ -381,6 +379,14 @@ int main(int argc, const char *argv[]) {
return 1;
}
+ // Create the output directory if the user specified one does not exist.
+ if (!llvm::sys::fs::exists(OutputDir.getValue())) {
+ llvm::sys::fs::create_directory(OutputDir.getValue());
+ }
+
+ if (!llvm::sys::fs::exists(GetServerOutputDirectory())) {
+ llvm::sys::fs::create_directory(GetServerOutputDirectory());
+ }
CommonOptionsParser &OP = ExpectedParser.get();
auto PCHOpts = std::make_shared<PCHContainerOperations>();
PCHOpts->registerWriter(std::make_unique<ObjectFilePCHContainerWriter>());
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp b/lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp
index 30a18e3..30a18e3 100644
--- a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp
+++ b/lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.cpp
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.h b/lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.h
index a0e4f47..a0e4f47 100644
--- a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerHeaderEmitter.h
+++ b/lldb/tools/lldb-rpc-gen/server/RPCServerHeaderEmitter.h
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp b/lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp
index a6d2528..a6d2528 100644
--- a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp
+++ b/lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.cpp
diff --git a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.h b/lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.h
index a371dc1..a371dc1 100644
--- a/lldb/tools/lldb-rpc/lldb-rpc-gen/server/RPCServerSourceEmitter.h
+++ b/lldb/tools/lldb-rpc-gen/server/RPCServerSourceEmitter.h
diff --git a/lldb/tools/lldb-rpc/CMakeLists.txt b/lldb/tools/lldb-rpc/CMakeLists.txt
new file mode 100644
index 0000000..fdd6cf9
--- /dev/null
+++ b/lldb/tools/lldb-rpc/CMakeLists.txt
@@ -0,0 +1,22 @@
+include(CheckCXXCompilerFlag)
+# Umbrella target for the entire framework is a default target.
+add_custom_target(lldb-rpc ALL)
+
+if(LLDB_CODESIGN_IDENTITY)
+ # Use explicit LLDB identity
+ set(LLVM_CODESIGNING_IDENTITY ${LLDB_CODESIGN_IDENTITY})
+else()
+ # Use explicit LLVM identity or default to ad-hoc signing if empty
+ if(NOT LLVM_CODESIGNING_IDENTITY)
+ set(LLVM_CODESIGNING_IDENTITY -)
+ endif()
+endif()
+
+# LLDBRPCGeneration.cmake needs the LLDB_RPC_GEN_EXE variable
+# which gets defined in the lldb-rpc-gen folder, so we're adding
+# this folder before we add that file.
+add_lldb_tool_subdirectory(lldb-rpc-gen)
+include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCGeneration.cmake)
+include(${CMAKE_CURRENT_SOURCE_DIR}/LLDBRPCHeaders.cmake)
+
+add_dependencies(lldb-rpc lldb-rpc-generate-sources liblldbrpc-headers)
diff --git a/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
new file mode 100644
index 0000000..a4cacf8
--- /dev/null
+++ b/lldb/tools/lldb-rpc/LLDBRPCGeneration.cmake
@@ -0,0 +1,80 @@
+if (NOT DEFINED LLDB_RPC_GEN_EXE)
+ message(FATAL_ERROR
+ "Unable to generate lldb-rpc sources because LLDB_RPC_GEN_EXE is not
+ defined. If you are cross-compiling, please build lldb-rpc-gen for your host
+ platform.")
+endif()
+set(lldb_rpc_generated_dir "${CMAKE_CURRENT_BINARY_DIR}/generated")
+set(lldb_rpc_server_generated_source_dir "${lldb_rpc_generated_dir}/server")
+
+file(GLOB api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SB*.h)
+# We don't generate SBCommunication
+list(REMOVE_ITEM api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SBCommunication.h)
+# SBDefines.h is mostly definitions and forward declarations, nothing to
+# generate.
+list(REMOVE_ITEM api_headers ${LLDB_SOURCE_DIR}/include/lldb/API/SBDefines.h)
+
+# Generate the list of byproducts. Note that we cannot just glob the files in
+# the directory with the generated sources because BYPRODUCTS needs to be known
+# at configure time but the files are generated at build time.
+set(lldb_rpc_gen_byproducts
+ ${lldb_rpc_generated_dir}/SBClasses.def
+ ${lldb_rpc_generated_dir}/SBAPI.def
+ ${lldb_rpc_generated_dir}/lldb.py
+ ${lldb_rpc_server_generated_source_dir}/SBAPI.h
+)
+
+set(lldb_rpc_gen_server_impl_files)
+foreach(path ${api_headers})
+ get_filename_component(filename_no_ext ${path} NAME_WLE)
+
+ set(server_header_file "Server_${filename_no_ext}.h")
+ list(APPEND lldb_rpc_gen_byproducts "${lldb_rpc_server_generated_source_dir}/${server_header_file}")
+
+ set(server_impl_file "Server_${filename_no_ext}.cpp")
+ list(APPEND lldb_rpc_gen_byproducts "${lldb_rpc_server_generated_source_dir}/${server_impl_file}")
+ list(APPEND lldb_rpc_gen_server_impl_files "${lldb_rpc_server_generated_source_dir}/${server_impl_file}")
+
+endforeach()
+
+# Make sure that the clang-resource-dir is set correctly or else the tool will
+# fail to run. This is only needed when we do a standalone build.
+set(clang_resource_dir_arg)
+if (TARGET clang-resource-headers)
+ set(clang_resource_headers_dir
+ $<TARGET_PROPERTY:clang-resource-headers,INTERFACE_INCLUDE_DIRECTORIES>)
+ set(clang_resource_dir_arg --extra-arg="-resource-dir=${clang_resource_headers_dir}/..")
+else()
+ set(clang_resource_dir_arg --extra-arg="-resource-dir=${LLDB_EXTERNAL_CLANG_RESOURCE_DIR}")
+endif()
+
+set(sysroot_arg)
+if (DEFINED TOOLCHAIN_TARGET_SYSROOTFS)
+ set(sysroot_arg --extra-arg="-resource-dir=${TOOLCHAIN_TARGET_SYSROOTFS}")
+endif()
+
+add_custom_command(OUTPUT ${lldb_rpc_gen_byproducts}
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${lldb_rpc_generated_dir}
+
+ COMMAND ${CMAKE_COMMAND} -E make_directory
+ ${lldb_rpc_server_generated_source_dir}
+
+ COMMAND ${LLDB_RPC_GEN_EXE}
+ -p ${CMAKE_BINARY_DIR}
+ --output-dir=${lldb_rpc_generated_dir}
+ ${sysroot_arg}
+ --extra-arg="-USWIG"
+ ${api_headers}
+
+ DEPENDS ${LLDB_RPC_GEN_EXE} ${api_headers}
+ COMMENT "Generating sources for lldb-rpc-server..."
+ WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+)
+
+add_custom_target(lldb-rpc-generate-sources
+ DEPENDS
+ ${lldb_rpc_gen_byproducts}
+ lldb-sbapi-dwarf-enums)
+
+add_dependencies(lldb-rpc-generate-sources clang-resource-headers)
diff --git a/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
new file mode 100644
index 0000000..6c363f4
--- /dev/null
+++ b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake
@@ -0,0 +1,101 @@
+set(derived_headers_location "${CMAKE_CURRENT_BINARY_DIR}/DerivedHeaders")
+
+# Obtain the original headers from their staged location in the build directory.
+set(original_headers_location "${CMAKE_BINARY_DIR}/include/lldb")
+set(headers_to_process
+ SBDefines.h
+ lldb-defines.h
+ lldb-enumerations.h
+ lldb-types.h
+)
+
+file(MAKE_DIRECTORY ${derived_headers_location})
+
+# Take the original headers and convert them RPC as necessary using the conversion script.
+set(original_headers)
+set(derived_headers)
+foreach(header ${headers_to_process})
+ set(original_header "${original_headers_location}/${header}")
+
+ get_filename_component(header_filename ${header} NAME)
+ string(REPLACE "lldb-" "lldb-rpc-" rpc_header_filename "${header_filename}")
+ set(derived_header "${derived_headers_location}/${rpc_header_filename}")
+
+ list(APPEND original_headers "${original_header}")
+ list(APPEND derived_headers "${derived_header}")
+ add_custom_command(OUTPUT ${derived_header}
+ COMMAND ${Python3_EXECUTABLE} ${LLDB_SOURCE_DIR}/scripts/convert-lldb-header-to-rpc-header.py
+ ${original_header} ${derived_header}
+ DEPENDS ${original_header}
+
+ COMMENT "Creating ${derived_header}"
+ )
+endforeach()
+
+# Do the same thing for any header files that were autogenerated.
+set(generated_headers_to_process
+ API/SBLanguages.h
+)
+foreach(header ${generated_headers_to_process})
+ set(original_header "${LLDB_OBJ_DIR}/include/lldb/${header}")
+
+ get_filename_component(header_filename ${header} NAME)
+ string(REPLACE "lldb-" "lldb-rpc-" rpc_header_filename "${header_filename}")
+ set(derived_header "${derived_headers_location}/${rpc_header_filename}")
+
+ list(APPEND original_headers "${original_header}")
+ list(APPEND derived_headers "${derived_header}")
+ add_custom_command(OUTPUT ${derived_header}
+ COMMAND ${CMAKE_COMMAND} -E copy ${original_header} ${derived_header}
+ COMMAND ${Python3_EXECUTABLE} ${LLDB_SOURCE_DIR}/scripts/convert-lldb-header-to-rpc-header.py
+ ${original_header} ${derived_header}
+ DEPENDS lldb-sbapi-dwarf-enums
+
+ COMMENT "Creating ${derived_header}"
+ )
+endforeach()
+
+add_custom_target(copy-aux-rpc-headers DEPENDS ${derived_headers})
+add_dependencies(copy-aux-rpc-headers liblldb-header-staging)
+
+list(APPEND public_headers
+ ${derived_headers_location}/SBDefines.h
+ ${derived_headers_location}/SBLanguages.h
+ ${derived_headers_location}/lldb-rpc-enumerations.h
+ ${derived_headers_location}/lldb-rpc-types.h
+ ${derived_headers_location}/lldb-rpc-defines.h
+)
+
+# Collect and preprocess headers for the framework bundle
+set(version_header
+ ${derived_headers_location}/lldb-rpc-defines.h
+)
+
+function(FixIncludePaths in subfolder out)
+ get_filename_component(base_name ${in} NAME)
+ set(parked_header ${CMAKE_CURRENT_BINARY_DIR}/ParkedHeaders/${subfolder}/${base_name})
+ set(${out} ${parked_header} PARENT_SCOPE)
+ find_program(unifdef_EXECUTABLE unifdef)
+
+ add_custom_command(OUTPUT ${parked_header}
+ COMMAND ${LLDB_SOURCE_DIR}/scripts/framework-header-fix.py
+ -f lldb_rpc -i ${in} -o ${parked_header} -p ${unifdef_EXECUTABLE} --unifdef_guards USWIG
+ DEPENDS ${in}
+ COMMENT "Fixing includes in ${in}"
+ )
+endfunction()
+
+set(preprocessed_headers)
+
+# Apply include-paths fix and any version fix on all headers and park them.
+foreach(source_header ${public_headers})
+ FixIncludePaths(${source_header} Headers parked_header)
+ list(APPEND preprocessed_headers ${parked_header})
+endforeach()
+
+# Wrap header preprocessing in a target, so liblldbrpc can depend on.
+add_custom_target(liblldbrpc-headers DEPENDS ${preprocessed_headers})
+add_dependencies(liblldbrpc-headers copy-aux-rpc-headers liblldb-header-staging)
+set_target_properties(liblldbrpc-headers PROPERTIES
+ LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/ParkedHeaders
+)
diff --git a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
index f7b5e3a..fbb005b 100644
--- a/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
+++ b/lldb/unittests/ScriptInterpreter/Python/PythonTestSuite.cpp
@@ -80,20 +80,6 @@ lldb_private::python::SWIGBridge::LLDBSwigPythonCreateCommandObject(
return python::PythonObject();
}
-python::PythonObject lldb_private::python::SWIGBridge::
- LLDBSwigPythonCreateScriptedBreakpointResolver(
- const char *python_class_name, const char *session_dictionary_name,
- const StructuredDataImpl &args, const lldb::BreakpointSP &bkpt_sp) {
- return python::PythonObject();
-}
-
-unsigned int
-lldb_private::python::SWIGBridge::LLDBSwigPythonCallBreakpointResolver(
- void *implementor, const char *method_name,
- lldb_private::SymbolContext *sym_ctx) {
- return 0;
-}
-
size_t lldb_private::python::SWIGBridge::LLDBSwigPython_CalculateNumChildren(
PyObject *implementor, uint32_t max) {
return 0;
@@ -144,6 +130,11 @@ lldb_private::python::LLDBSWIGPython_CastPyObjectToSBStream(PyObject *data) {
return nullptr;
}
+void *lldb_private::python::LLDBSWIGPython_CastPyObjectToSBSymbolContext(
+ PyObject *data) {
+ return nullptr;
+}
+
void *
lldb_private::python::LLDBSWIGPython_CastPyObjectToSBValue(PyObject *data) {
return nullptr;