diff options
Diffstat (limited to 'lldb')
155 files changed, 2743 insertions, 773 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/docs/resources/lldbgdbremote.md b/lldb/docs/resources/lldbgdbremote.md index 80c6809..36b95f1 100644 --- a/lldb/docs/resources/lldbgdbremote.md +++ b/lldb/docs/resources/lldbgdbremote.md @@ -2463,3 +2463,70 @@ omitting them will work fine; these numbers are always base 16. The length of the payload is not provided. A reliable, 8-bit clean, transport layer is assumed. + +## Wasm Packets + +The packet below are supported by the +[WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) and +[V8](https://v8.dev) Wasm runtimes. + + +### 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. Necessary to show +stack traces. + +### qWasmGlobal + +Get the value of a Wasm global variable for the given frame index at the given +variable index. The indexes are encoded as base 10. The result is a hex-encoded +address from where to read the value. + +``` +send packet: $qWasmGlobal:0;2#cb +read packet: $e0030100#b9 +``` + +**Priority to Implement:** Only required for Wasm support. Necessary to show +variables. + + +### qWasmLocal + +Get the value of a Wasm function argument or local variable for the given frame +index at the given variable index. The indexes are encoded as base 10. The +result is a hex-encoded address from where to read the value. + + +``` +send packet: $qWasmLocal:0;2#cb +read packet: $e0030100#b9 +``` + +**Priority to Implement:** Only required for Wasm support. Necessary to show +variables. + + +### qWasmStackValue + +Get the value of a Wasm local variable from the Wasm operand stack, for the +given frame index at the given variable index. The indexes are encoded as base +10. The result is a hex-encoded address from where to read value. + +``` +send packet: $qWasmStackValue:0;2#cb +read packet: $e0030100#b9 +``` + +**Priority to Implement:** Only required for Wasm support. Necessary to show +variables. 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/Expression/DWARFExpression.h b/lldb/include/lldb/Expression/DWARFExpression.h index 37853c0..8fcc5d3 100644 --- a/lldb/include/lldb/Expression/DWARFExpression.h +++ b/lldb/include/lldb/Expression/DWARFExpression.h @@ -52,10 +52,10 @@ public: GetVendorDWARFOpcodeSize(const DataExtractor &data, const lldb::offset_t data_offset, const uint8_t op) const = 0; - virtual bool ParseVendorDWARFOpcode(uint8_t op, - const DataExtractor &opcodes, - lldb::offset_t &offset, - Stack &stack) const = 0; + virtual bool + ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, Stack &stack) const = 0; Delegate(const Delegate &) = delete; Delegate &operator=(const Delegate &) = delete; @@ -163,6 +163,10 @@ public: bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op) const; + static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + uint32_t reg_num, Value &value); + private: /// A data extractor capable of reading opcode bytes DataExtractor m_data; 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/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/builders/__init__.py b/lldb/packages/Python/lldbsuite/test/builders/__init__.py index 9dd82cb..7331526 100644 --- a/lldb/packages/Python/lldbsuite/test/builders/__init__.py +++ b/lldb/packages/Python/lldbsuite/test/builders/__init__.py @@ -8,7 +8,15 @@ factory method below hands out builders based on the given platform. def get_builder(platform): """Returns a Builder instance for the given platform.""" - if platform == "darwin": + if platform in [ + "bridgeos", + "darwin", + "ios", + "macosx", + "tvos", + "watchos", + "xros", + ]: from .darwin import BuilderDarwin return BuilderDarwin() 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/lldbplatformutil.py b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py index a1ab060..cea6270 100644 --- a/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py +++ b/lldb/packages/Python/lldbsuite/test/lldbplatformutil.py @@ -229,7 +229,8 @@ def hasChattyStderr(test_case): def builder_module(): - return get_builder(sys.platform) + """Return the builder for the target platform.""" + return get_builder(getPlatform()) def getArchitecture(): diff --git a/lldb/packages/Python/lldbsuite/test/lldbtest.py b/lldb/packages/Python/lldbsuite/test/lldbtest.py index 63fadb5..0fc85fc 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() @@ -1514,7 +1517,7 @@ class Base(unittest.TestCase): testname = self.getBuildDirBasename() module = builder_module() - command = builder_module().getBuildCommand( + command = module.getBuildCommand( debug_info, architecture, compiler, @@ -1775,16 +1778,15 @@ class LLDBTestCaseFactory(type): attrvalue, "__no_debug_info_test__", False ): # If any debug info categories were explicitly tagged, assume that list to be - # authoritative. If none were specified, try with all debug - # info formats. + # authoritative. If none were specified, try with all debug info formats. + test_method_categories = set(getattr(attrvalue, "categories", [])) all_dbginfo_categories = set( test_categories.debug_info_categories.keys() ) - categories = ( - set(getattr(attrvalue, "categories", [])) & all_dbginfo_categories - ) - if not categories: - categories = [ + dbginfo_categories = test_method_categories & all_dbginfo_categories + other_categories = list(test_method_categories - all_dbginfo_categories) + if not dbginfo_categories: + dbginfo_categories = [ category for category, can_replicate in test_categories.debug_info_categories.items() if can_replicate @@ -1796,9 +1798,8 @@ class LLDBTestCaseFactory(type): skip_for_debug_info_cat_fn = getattr( attrvalue, "__skip_for_debug_info_cat_fn__", no_reason ) - for cat in categories: + for cat in dbginfo_categories: - @decorators.add_test_categories([cat]) @wraps(attrvalue) def test_method(self, attrvalue=attrvalue): return attrvalue(self) @@ -1806,6 +1807,7 @@ class LLDBTestCaseFactory(type): method_name = attrname + "_" + cat test_method.__name__ = method_name test_method.debug_info = cat + test_method.categories = other_categories + [cat] xfail_reason = xfail_for_debug_info_cat_fn(cat) if xfail_reason: diff --git a/lldb/scripts/framework-header-fix.py b/lldb/scripts/framework-header-fix.py index aa034db..36c5c67 100755 --- a/lldb/scripts/framework-header-fix.py +++ b/lldb/scripts/framework-header-fix.py @@ -112,7 +112,7 @@ def main(): # but passing them in with dashes for this script causes argparse to think that they're # arguments in and of themself, so they need to passed in without dashes. if args.unifdef_guards: - unifdef_guards = ["-" + guard for guard in args.unifdef_guards] + unifdef_guards = ["-U" + guard for guard in args.unifdef_guards] # Create the framework's header dir if it doesn't already exist if not os.path.exists(os.path.dirname(output_file_path)): diff --git a/lldb/source/API/CMakeLists.txt b/lldb/source/API/CMakeLists.txt index 0687c84..fdd6b3b 100644 --- a/lldb/source/API/CMakeLists.txt +++ b/lldb/source/API/CMakeLists.txt @@ -327,6 +327,7 @@ foreach(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} @@ -339,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/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/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/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 79bc6c8..391e277 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -91,9 +91,10 @@ void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) { m_reg_kind = reg_kind; } -static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx, - lldb::RegisterKind reg_kind, - uint32_t reg_num, Value &value) { +llvm::Error +DWARFExpression::ReadRegisterValueAsScalar(RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + uint32_t reg_num, Value &value) { if (reg_ctx == nullptr) return llvm::createStringError("no register context in frame"); @@ -2302,7 +2303,8 @@ llvm::Expected<Value> DWARFExpression::Evaluate( default: if (dwarf_cu) { - if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, stack)) { + if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, reg_ctx, + reg_kind, stack)) { break; } } diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 17ea159..329768d 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -102,22 +102,23 @@ public: m_persistent_variable_sp->GetName(), mem, eAddressTypeLoad, map.GetAddressByteSize()); - if (m_persistent_variable_sp->m_flags & - ExpressionVariable::EVKeepInTarget) { - if (used_policy == IRMemoryMap::eAllocationPolicyMirror) { + if (used_policy == IRMemoryMap::eAllocationPolicyMirror) { + if (m_persistent_variable_sp->m_flags & + ExpressionVariable::EVKeepInTarget) { // Clear the flag if the variable will never be deallocated. Status leak_error; map.Leak(mem, leak_error); m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVNeedsAllocation; - } else { - // If the variable cannot be kept in target, clear this flag... - m_persistent_variable_sp->m_flags &= - ~ExpressionVariable::EVKeepInTarget; - // ...and set the flag to copy the value during dematerialization. - m_persistent_variable_sp->m_flags |= - ExpressionVariable::EVNeedsFreezeDry; } + } else { + // If we cannot allocate memory in the process, + // - clear the 'EVKeepInTarget' flag to ensure that 'm_live_sp' is reset + // during dematerialization, + m_persistent_variable_sp->m_flags &= ~ExpressionVariable::EVKeepInTarget; + // - set the 'EVNeedsFreezeDry' flag so that the value is copied to + // 'm_frozen_sp' during dematerialization. + m_persistent_variable_sp->m_flags |= ExpressionVariable::EVNeedsFreezeDry; } // Write the contents of the variable to the area. diff --git a/lldb/source/Host/windows/MainLoopWindows.cpp b/lldb/source/Host/windows/MainLoopWindows.cpp index c1a0182..c0b1079 100644 --- a/lldb/source/Host/windows/MainLoopWindows.cpp +++ b/lldb/source/Host/windows/MainLoopWindows.cpp @@ -223,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; } @@ -235,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/Interpreter/ScriptInterpreter.cpp b/lldb/source/Interpreter/ScriptInterpreter.cpp index ae913e6..6a654a0 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; + return {}; +} + std::optional<MemoryRegionInfo> ScriptInterpreter::GetOpaqueTypeFromSBMemoryRegionInfo( const lldb::SBMemoryRegionInfo &mem_region) const { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 9f77fbc..214e260 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -1991,7 +1991,7 @@ void ClangExpressionDeclMap::AddContextClassType(NameSearchContext &context, const bool is_artificial = false; CXXMethodDecl *method_decl = m_clang_ast_context->AddMethodToCXXRecordType( - copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", nullptr, + copied_clang_type.GetOpaqueQualType(), "$__lldb_expr", /*asm_label=*/{}, method_type, lldb::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); diff --git a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp index 2adde02..5e429a9 100644 --- a/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp +++ b/lldb/source/Plugins/Instruction/RISCV/EmulateInstructionRISCV.cpp @@ -1807,7 +1807,7 @@ RISCVSingleStepBreakpointLocationsPredictor::GetBreakpointLocations( Log *log = GetLog(LLDBLog::Unwind); LLDB_LOGF(log, "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find " - "corresponding load reserve insturuction", + "corresponding load reserve instruction", __FUNCTION__); return {*pc + (inst->is_rvc ? 2u : 4u)}; } @@ -1839,7 +1839,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence( EmulateInstructionRISCV *riscv_emulator = static_cast<EmulateInstructionRISCV *>(m_emulator_up.get()); - // Handle instructions between LR and SC. According to unprivilleged + // Handle instructions between LR and SC. According to unprivileged // RISC-V ISA there can be at most 16 instructions in the sequence. lldb::addr_t entry_pc = pc; // LR instruction address @@ -1872,7 +1872,7 @@ RISCVSingleStepBreakpointLocationsPredictor::HandleAtomicSequence( Log *log = GetLog(LLDBLog::Unwind); LLDB_LOGF(log, "RISCVSingleStepBreakpointLocationsPredictor::%s: can't find " - "corresponding store conditional insturuction", + "corresponding store conditional instruction", __FUNCTION__); return {entry_pc + (lr_inst->is_rvc ? 2u : 4u)}; } 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/ObjectFile/wasm/ObjectFileWasm.cpp b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp index 67963a7..b1efd25 100644 --- a/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp +++ b/lldb/source/Plugins/ObjectFile/wasm/ObjectFileWasm.cpp @@ -376,9 +376,13 @@ DataExtractor ObjectFileWasm::ReadImageData(offset_t offset, uint32_t size) { DataBufferSP buffer_sp(data_up.release()); data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); } + } else if (offset < m_data.GetByteSize()) { + size = + std::min(static_cast<uint64_t>(size), m_data.GetByteSize() - offset); + return DataExtractor(m_data.GetDataStart() + offset, size, GetByteOrder(), + GetAddressByteSize()); } } - data.SetByteOrder(GetByteOrder()); return data; } 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 ®s = (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, ®set, - &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, ®set, - &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(), - ®set, &ioVec, ioVec.iov_len) + uint32_t max_supported = + (hwbType == eDREGTypeWATCH) ? m_max_hwp_supported : m_max_hbp_supported; + auto ®s = (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, ®set, + &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> ®s) { + 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, ®set, + &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> ®s); + +} // 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 ® : 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..779b97e --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/CMakeLists.txt @@ -0,0 +1,11 @@ +add_lldb_library(lldbPluginProcessWasm PLUGIN + ProcessWasm.cpp + RegisterContextWasm.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..580e8c1 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.cpp @@ -0,0 +1,166 @@ +//===----------------------------------------------------------------------===// +// +// 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; +} + +llvm::Expected<lldb::DataBufferSP> +ProcessWasm::GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, + int index) { + StreamString packet; + switch (kind) { + case eWasmTagLocal: + packet.Printf("qWasmLocal:"); + break; + case eWasmTagGlobal: + packet.Printf("qWasmGlobal:"); + break; + case eWasmTagOperandStack: + packet.PutCString("qWasmStackValue:"); + break; + case eWasmTagNotAWasmLocation: + return llvm::createStringError("not a Wasm location"); + } + packet.Printf("%d;%d", frame_index, index); + + StringExtractorGDBRemote response; + if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response) != + GDBRemoteCommunication::PacketResult::Success) + return llvm::createStringError("failed to send Wasm variable"); + + if (!response.IsNormalResponse()) + return llvm::createStringError("failed to get response for Wasm variable"); + + WritableDataBufferSP buffer_sp( + new DataBufferHeap(response.GetStringRef().size() / 2, 0)); + response.GetHexBytes(buffer_sp->GetData(), '\xcc'); + return buffer_sp; +} diff --git a/lldb/source/Plugins/Process/wasm/ProcessWasm.h b/lldb/source/Plugins/Process/wasm/ProcessWasm.h new file mode 100644 index 0000000..22effe7 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ProcessWasm.h @@ -0,0 +1,99 @@ +//===----------------------------------------------------------------------===// +// +// 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" +#include "Utility/WasmVirtualRegisters.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); + + /// Query the value of a WebAssembly variable from the WebAssembly + /// remote process. + llvm::Expected<lldb::DataBufferSP> + GetWasmVariable(WasmVirtualRegisterKinds kind, int frame_index, int index); + +protected: + std::shared_ptr<process_gdb_remote::ThreadGDBRemote> + CreateThread(lldb::tid_t tid) override; + +private: + friend class UnwindWasm; + friend class ThreadWasm; + + 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/RegisterContextWasm.cpp b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp new file mode 100644 index 0000000..b468171 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.cpp @@ -0,0 +1,109 @@ +//===----------------------------------------------------------------------===// +// +// 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 "RegisterContextWasm.h" +#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" +#include "ProcessWasm.h" +#include "ThreadWasm.h" +#include "lldb/Utility/LLDBLog.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "llvm/Support/Error.h" +#include <memory> + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; +using namespace lldb_private::wasm; + +RegisterContextWasm::RegisterContextWasm( + wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, + GDBRemoteDynamicRegisterInfoSP reg_info_sp) + : GDBRemoteRegisterContext(thread, concrete_frame_idx, reg_info_sp, false, + false) {} + +RegisterContextWasm::~RegisterContextWasm() = default; + +uint32_t RegisterContextWasm::ConvertRegisterKindToRegisterNumber( + lldb::RegisterKind kind, uint32_t num) { + return num; +} + +size_t RegisterContextWasm::GetRegisterCount() { + // Wasm has no registers. + return 0; +} + +const RegisterInfo *RegisterContextWasm::GetRegisterInfoAtIndex(size_t reg) { + uint32_t tag = GetWasmVirtualRegisterTag(reg); + if (tag == eWasmTagNotAWasmLocation) + return m_reg_info_sp->GetRegisterInfoAtIndex( + GetWasmVirtualRegisterIndex(reg)); + + auto it = m_register_map.find(reg); + if (it == m_register_map.end()) { + WasmVirtualRegisterKinds kind = static_cast<WasmVirtualRegisterKinds>(tag); + std::tie(it, std::ignore) = m_register_map.insert( + {reg, std::make_unique<WasmVirtualRegisterInfo>( + kind, GetWasmVirtualRegisterIndex(reg))}); + } + return it->second.get(); +} + +size_t RegisterContextWasm::GetRegisterSetCount() { return 0; } + +const RegisterSet *RegisterContextWasm::GetRegisterSet(size_t reg_set) { + // Wasm has no registers. + return nullptr; +} + +bool RegisterContextWasm::ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) { + // The only real registers is the PC. + if (reg_info->name) + return GDBRemoteRegisterContext::ReadRegister(reg_info, value); + + // Read the virtual registers. + ThreadWasm *thread = static_cast<ThreadWasm *>(&GetThread()); + ProcessWasm *process = static_cast<ProcessWasm *>(thread->GetProcess().get()); + if (!thread) + return false; + + uint32_t frame_index = m_concrete_frame_idx; + WasmVirtualRegisterInfo *wasm_reg_info = + static_cast<WasmVirtualRegisterInfo *>( + const_cast<RegisterInfo *>(reg_info)); + + llvm::Expected<DataBufferSP> maybe_buffer = process->GetWasmVariable( + wasm_reg_info->kind, frame_index, wasm_reg_info->index); + if (!maybe_buffer) { + LLDB_LOG_ERROR(GetLog(LLDBLog::Process), maybe_buffer.takeError(), + "Failed to read Wasm local: {0}"); + return false; + } + + DataBufferSP buffer_sp = *maybe_buffer; + DataExtractor reg_data(buffer_sp, process->GetByteOrder(), + process->GetAddressByteSize()); + wasm_reg_info->byte_size = buffer_sp->GetByteSize(); + wasm_reg_info->encoding = lldb::eEncodingUint; + + Status error = value.SetValueFromData( + *reg_info, reg_data, reg_info->byte_offset, /*partial_data_ok=*/false); + return error.Success(); +} + +void RegisterContextWasm::InvalidateAllRegisters() {} + +bool RegisterContextWasm::WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) { + // The only real registers is the PC. + if (reg_info->name) + return GDBRemoteRegisterContext::WriteRegister(reg_info, value); + return false; +} diff --git a/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h new file mode 100644 index 0000000..7e63eb8 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/RegisterContextWasm.h @@ -0,0 +1,69 @@ +//===----------------------------------------------------------------------===// +// +// 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_REGISTERCONTEXTWASM_H +#define LLDB_SOURCE_PLUGINS_PROCESS_WASM_REGISTERCONTEXTWASM_H + +#include "Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h" +#include "ThreadWasm.h" +#include "Utility/WasmVirtualRegisters.h" +#include "lldb/lldb-private-types.h" +#include <unordered_map> + +namespace lldb_private { +namespace wasm { + +class RegisterContextWasm; + +typedef std::shared_ptr<RegisterContextWasm> RegisterContextWasmSP; + +struct WasmVirtualRegisterInfo : public RegisterInfo { + WasmVirtualRegisterKinds kind; + uint32_t index; + + WasmVirtualRegisterInfo(WasmVirtualRegisterKinds kind, uint32_t index) + : RegisterInfo(), kind(kind), index(index) {} +}; + +class RegisterContextWasm + : public process_gdb_remote::GDBRemoteRegisterContext { +public: + RegisterContextWasm( + wasm::ThreadWasm &thread, uint32_t concrete_frame_idx, + process_gdb_remote::GDBRemoteDynamicRegisterInfoSP reg_info_sp); + + ~RegisterContextWasm() override; + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override; + + void InvalidateAllRegisters() override; + + size_t GetRegisterCount() override; + + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override; + + size_t GetRegisterSetCount() override; + + const RegisterSet *GetRegisterSet(size_t reg_set) override; + + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue &value) override; + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue &value) override; + +private: + std::unordered_map<size_t, std::unique_ptr<WasmVirtualRegisterInfo>> + m_register_map; +}; + +} // 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..0666b75 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.cpp @@ -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 +// +//===----------------------------------------------------------------------===// + +#include "ThreadWasm.h" + +#include "ProcessWasm.h" +#include "RegisterContextWasm.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"); +} + +lldb::RegisterContextSP +ThreadWasm::CreateRegisterContextForFrame(StackFrame *frame) { + uint32_t concrete_frame_idx = 0; + ProcessSP process_sp(GetProcess()); + ProcessWasm *wasm_process = static_cast<ProcessWasm *>(process_sp.get()); + + if (frame) + concrete_frame_idx = frame->GetConcreteFrameIndex(); + + if (concrete_frame_idx == 0) + return std::make_shared<RegisterContextWasm>( + *this, concrete_frame_idx, wasm_process->GetRegisterInfo()); + + return GetUnwinder().CreateRegisterContextForFrame(frame); +} diff --git a/lldb/source/Plugins/Process/wasm/ThreadWasm.h b/lldb/source/Plugins/Process/wasm/ThreadWasm.h new file mode 100644 index 0000000..c2f5762 --- /dev/null +++ b/lldb/source/Plugins/Process/wasm/ThreadWasm.h @@ -0,0 +1,41 @@ +//===----------------------------------------------------------------------===// +// +// 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(); + + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override; + +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 ®_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 457182a..ce77569 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -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) { 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/SymbolFile/DWARF/CMakeLists.txt b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt index 212cc36..c3f1bb5 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt +++ b/lldb/source/Plugins/SymbolFile/DWARF/CMakeLists.txt @@ -35,6 +35,7 @@ add_lldb_library(lldbPluginSymbolFileDWARF PLUGIN SymbolFileDWARF.cpp SymbolFileDWARFDwo.cpp SymbolFileDWARFDebugMap.cpp + SymbolFileWasm.cpp UniqueDWARFASTType.cpp LINK_COMPONENTS diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index ba65f50..e58e28a 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -249,6 +249,14 @@ static unsigned GetCXXMethodCVQuals(const DWARFDIE &subprogram, return cv_quals; } +static std::string MakeLLDBFuncAsmLabel(const DWARFDIE &die) { + char const *name = die.GetMangledName(/*substitute_name_allowed*/ false); + if (!name) + return {}; + + return name; +} + TypeSP DWARFASTParserClang::ParseTypeFromClangModule(const SymbolContext &sc, const DWARFDIE &die, Log *log) { @@ -1231,7 +1239,7 @@ std::pair<bool, TypeSP> DWARFASTParserClang::ParseCXXMethod( clang::CXXMethodDecl *cxx_method_decl = m_ast.AddMethodToCXXRecordType( class_opaque_type.GetOpaqueQualType(), attrs.name.GetCString(), - attrs.mangled_name, clang_type, accessibility, attrs.is_virtual, + MakeLLDBFuncAsmLabel(die), clang_type, accessibility, attrs.is_virtual, is_static, attrs.is_inline, attrs.is_explicit, is_attr_used, attrs.is_artificial); @@ -1384,7 +1392,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), name, clang_type, attrs.storage, - attrs.is_inline); + attrs.is_inline, MakeLLDBFuncAsmLabel(die)); std::free(name_buf); if (has_template_params) { @@ -1394,7 +1402,7 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, ignore_containing_context ? m_ast.GetTranslationUnitDecl() : containing_decl_ctx, GetOwningClangModule(die), attrs.name.GetStringRef(), clang_type, - attrs.storage, attrs.is_inline); + attrs.storage, attrs.is_inline, /*asm_label=*/{}); clang::FunctionTemplateDecl *func_template_decl = m_ast.CreateFunctionTemplateDecl( containing_decl_ctx, GetOwningClangModule(die), @@ -1406,20 +1414,6 @@ DWARFASTParserClang::ParseSubroutine(const DWARFDIE &die, lldbassert(function_decl); if (function_decl) { - // Attach an asm(<mangled_name>) label to the FunctionDecl. - // This ensures that clang::CodeGen emits function calls - // using symbols that are mangled according to the DW_AT_linkage_name. - // If we didn't do this, the external symbols wouldn't exactly - // match the mangled name LLDB knows about and the IRExecutionUnit - // would have to fall back to searching object files for - // approximately matching function names. The motivating - // example is generating calls to ABI-tagged template functions. - // This is done separately for member functions in - // AddMethodToCXXRecordType. - if (attrs.mangled_name) - function_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - m_ast.getASTContext(), attrs.mangled_name, /*literal=*/false)); - LinkDeclContextToDIE(function_decl, die); const clang::FunctionProtoType *function_prototype( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp index a66af5b..94fc2e83 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.cpp @@ -736,9 +736,11 @@ DWARFUnit::GetVendorDWARFOpcodeSize(const DataExtractor &data, bool DWARFUnit::ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, lldb::offset_t &offset, + RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, std::vector<Value> &stack) const { return GetSymbolFileDWARF().ParseVendorDWARFOpcode(op, opcodes, offset, - stack); + reg_ctx, reg_kind, stack); } bool DWARFUnit::ParseDWARFLocationList( diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h index f55400e..91a6938 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFUnit.h @@ -164,9 +164,11 @@ public: const lldb::offset_t data_offset, const uint8_t op) const override; - bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, - lldb::offset_t &offset, - std::vector<Value> &stack) const override; + virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, + RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + std::vector<Value> &stack) const override; bool ParseDWARFLocationList(const DataExtractor &data, DWARFExpressionList &loc_list) const; diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index 4b4a582..41ab8d1 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -41,6 +41,7 @@ #include "Plugins/ExpressionParser/Clang/ClangUtil.h" #include "Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileWasm.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/CompileUnit.h" @@ -327,6 +328,9 @@ llvm::StringRef SymbolFileDWARF::GetPluginDescriptionStatic() { } SymbolFile *SymbolFileDWARF::CreateInstance(ObjectFileSP objfile_sp) { + if (objfile_sp->GetArchitecture().GetTriple().isWasm()) + return new SymbolFileWasm(std::move(objfile_sp), + /*dwo_section_list*/ nullptr); return new SymbolFileDWARF(std::move(objfile_sp), /*dwo_section_list*/ nullptr); } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h index 2dc862c..56d8ccb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h @@ -329,6 +329,8 @@ public: virtual bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, lldb::offset_t &offset, + RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, std::vector<Value> &stack) const { return false; } @@ -556,6 +558,7 @@ protected: /// an index that identifies the .DWO or .o file. std::optional<uint64_t> m_file_index; }; + } // namespace dwarf } // namespace lldb_private::plugin diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp index c1829ab..52de3ab 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.cpp @@ -97,9 +97,11 @@ uint64_t SymbolFileDWARFDwo::GetDebugInfoSize(bool load_all_debug_info) { } bool SymbolFileDWARFDwo::ParseVendorDWARFOpcode( - uint8_t op, const lldb_private::DataExtractor &opcodes, - lldb::offset_t &offset, std::vector<lldb_private::Value> &stack) const { - return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset, stack); + uint8_t op, const DataExtractor &opcodes, lldb::offset_t &offset, + RegisterContext *reg_ctx, lldb::RegisterKind reg_kind, + std::vector<Value> &stack) const { + return GetBaseSymbolFile().ParseVendorDWARFOpcode(op, opcodes, offset, + reg_ctx, reg_kind, stack); } llvm::DenseMap<const DWARFDebugInfoEntry *, Type *> & diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h index 75f5986..1ab6494 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h @@ -50,7 +50,8 @@ public: uint64_t GetDebugInfoSize(bool load_all_debug_info = false) override; bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, - lldb::offset_t &offset, + lldb::offset_t &offset, RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, std::vector<Value> &stack) const override; void FindGlobalVariables(ConstString name, diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.cpp new file mode 100644 index 0000000..e25a89c --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.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 "SymbolFileWasm.h" +#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h" +#include "Utility/WasmVirtualRegisters.h" +#include "lldb/Utility/LLDBLog.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::plugin::dwarf; + +SymbolFileWasm::SymbolFileWasm(ObjectFileSP objfile_sp, + SectionList *dwo_section_list) + : SymbolFileDWARF(objfile_sp, dwo_section_list) {} + +SymbolFileWasm::~SymbolFileWasm() = default; + +lldb::offset_t +SymbolFileWasm::GetVendorDWARFOpcodeSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const { + if (op != llvm::dwarf::DW_OP_WASM_location) + return LLDB_INVALID_OFFSET; + + lldb::offset_t offset = data_offset; + const uint8_t wasm_op = data.GetU8(&offset); + switch (wasm_op) { + case 0: // LOCAL + case 1: // GLOBAL_FIXED + case 2: // OPERAND_STACK + data.GetULEB128(&offset); + break; + case 3: // GLOBAL_RELOC + data.GetU32(&offset); + break; + default: + return LLDB_INVALID_OFFSET; + } + + return offset - data_offset; +} + +bool SymbolFileWasm::ParseVendorDWARFOpcode(uint8_t op, + const DataExtractor &opcodes, + lldb::offset_t &offset, + RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + std::vector<Value> &stack) const { + if (op != llvm::dwarf::DW_OP_WASM_location) + return false; + + uint32_t index = 0; + uint8_t tag = eWasmTagNotAWasmLocation; + + /// |DWARF Location Index | WebAssembly Construct | + /// |---------------------|-----------------------| + /// |0 | Local | + /// |1 or 3 | Global | + /// |2 | Operand Stack | + const uint8_t wasm_op = opcodes.GetU8(&offset); + switch (wasm_op) { + case 0: // LOCAL + index = opcodes.GetULEB128(&offset); + tag = eWasmTagLocal; + break; + case 1: // GLOBAL_FIXED + index = opcodes.GetULEB128(&offset); + tag = eWasmTagGlobal; + break; + case 2: // OPERAND_STACK + index = opcodes.GetULEB128(&offset); + tag = eWasmTagOperandStack; + break; + case 3: // GLOBAL_RELOC + index = opcodes.GetU32(&offset); + tag = eWasmTagGlobal; + break; + default: + return false; + } + + const uint32_t reg_num = GetWasmRegister(tag, index); + + Value tmp; + llvm::Error error = DWARFExpression::ReadRegisterValueAsScalar( + reg_ctx, reg_kind, reg_num, tmp); + if (error) { + LLDB_LOG_ERROR(GetLog(DWARFLog::DebugInfo), std::move(error), "{0}"); + return false; + } + + stack.push_back(tmp); + return true; +} diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h new file mode 100644 index 0000000..0e0b742 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileWasm.h @@ -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 +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEWASM_H +#define LLDB_SOURCE_PLUGINS_SYMBOLFILE_DWARF_SYMBOLFILEWASM_H + +#include "SymbolFileDWARF.h" + +namespace lldb_private::plugin { +namespace dwarf { +class SymbolFileWasm : public SymbolFileDWARF { +public: + SymbolFileWasm(lldb::ObjectFileSP objfile_sp, SectionList *dwo_section_list); + + ~SymbolFileWasm() override; + + lldb::offset_t GetVendorDWARFOpcodeSize(const DataExtractor &data, + const lldb::offset_t data_offset, + const uint8_t op) const override; + + bool ParseVendorDWARFOpcode(uint8_t op, const DataExtractor &opcodes, + lldb::offset_t &offset, RegisterContext *reg_ctx, + lldb::RegisterKind reg_kind, + std::vector<Value> &stack) const override; +}; +} // namespace dwarf +} // namespace lldb_private::plugin + +#endif diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 702ec5e..8137622 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -88,7 +88,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks { MethodOptions::CompilerGenerated; function_decl = m_clang.AddMethodToCXXRecordType( parent_ty, proc_name, - /*mangled_name=*/nullptr, func_ct, /*access=*/access_type, + /*asm_label=*/{}, func_ct, /*access=*/access_type, /*is_virtual=*/is_virtual, /*is_static=*/is_static, /*is_inline=*/false, /*is_explicit=*/false, /*is_attr_used=*/false, /*is_artificial=*/is_artificial); @@ -903,7 +903,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, if (!function_decl) { function_decl = m_clang.AddMethodToCXXRecordType( parent_opaque_ty, func_name, - /*mangled_name=*/nullptr, func_ct, + /*asm_label=*/{}, func_ct, /*access=*/lldb::AccessType::eAccessPublic, /*is_virtual=*/false, /*is_static=*/false, /*is_inline=*/false, /*is_explicit=*/false, @@ -913,7 +913,7 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id, } else { function_decl = m_clang.CreateFunctionDeclaration( parent, OptionalClangModuleID(), func_name, func_ct, func_storage, - is_inline); + is_inline, /*asm_label=*/{}); CreateFunctionParameters(func_id, *function_decl, param_count); } return function_decl; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h index 1f888f4..98b965c 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.h @@ -65,7 +65,7 @@ struct CVTagRecord { } llvm::StringRef name() const { - if (m_kind == Struct || m_kind == Union) + if (m_kind == Struct || m_kind == Class) return cvclass.Name; if (m_kind == Enum) return cvenum.Name; diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp index 807ee5b..1c575e9 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/UdtRecordCompleter.cpp @@ -111,9 +111,8 @@ void UdtRecordCompleter::AddMethod(llvm::StringRef name, TypeIndex type_idx, bool is_artificial = (options & MethodOptions::CompilerGenerated) == MethodOptions::CompilerGenerated; m_ast_builder.clang().AddMethodToCXXRecordType( - derived_opaque_ty, name.data(), nullptr, method_ct, - access_type, attrs.isVirtual(), attrs.isStatic(), false, false, false, - is_artificial); + derived_opaque_ty, name.data(), /*asm_label=*/{}, method_ct, access_type, + attrs.isVirtual(), attrs.isStatic(), false, false, false, is_artificial); m_cxx_record_map[derived_opaque_ty].insert({name, method_ct}); } diff --git a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp index 0090d8f..8b8eac6e 100644 --- a/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp +++ b/lldb/source/Plugins/SymbolFile/PDB/PDBASTParser.cpp @@ -954,7 +954,8 @@ PDBASTParser::GetDeclForSymbol(const llvm::pdb::PDBSymbol &symbol) { auto decl = m_ast.CreateFunctionDeclaration( decl_context, OptionalClangModuleID(), name, - type->GetForwardCompilerType(), storage, func->hasInlineAttribute()); + type->GetForwardCompilerType(), storage, func->hasInlineAttribute(), + /*asm_label=*/{}); std::vector<clang::ParmVarDecl *> params; if (std::unique_ptr<PDBSymbolTypeFunctionSig> sig = func->getSignature()) { @@ -1446,7 +1447,7 @@ PDBASTParser::AddRecordMethod(lldb_private::SymbolFile &symbol_file, // TODO: get mangled name for the method. return m_ast.AddMethodToCXXRecordType( record_type.GetOpaqueQualType(), name.c_str(), - /*mangled_name*/ nullptr, method_comp_type, access, method.isVirtual(), + /*asm_label=*/{}, method_comp_type, access, method.isVirtual(), method.isStatic(), method.hasInlineAttribute(), /*is_explicit*/ false, // FIXME: Need this field in CodeView. /*is_attr_used*/ false, diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index 256952dc..836f9fe 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -2137,7 +2137,7 @@ std::string TypeSystemClang::GetTypeNameForDecl(const NamedDecl *named_decl, FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_clang_type, - clang::StorageClass storage, bool is_inline) { + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label) { FunctionDecl *func_decl = nullptr; ASTContext &ast = getASTContext(); if (!decl_ctx) @@ -2158,6 +2158,21 @@ FunctionDecl *TypeSystemClang::CreateFunctionDeclaration( func_decl->setConstexprKind(isConstexprSpecified ? ConstexprSpecKind::Constexpr : ConstexprSpecKind::Unspecified); + + // Attach an asm(<mangled_name>) label to the FunctionDecl. + // This ensures that clang::CodeGen emits function calls + // using symbols that are mangled according to the DW_AT_linkage_name. + // If we didn't do this, the external symbols wouldn't exactly + // match the mangled name LLDB knows about and the IRExecutionUnit + // would have to fall back to searching object files for + // approximately matching function names. The motivating + // example is generating calls to ABI-tagged template functions. + // This is done separately for member functions in + // AddMethodToCXXRecordType. + if (!asm_label.empty()) + func_decl->addAttr(clang::AsmLabelAttr::CreateImplicit(ast, asm_label, + /*literal=*/true)); + SetOwningModule(func_decl, owning_module); decl_ctx->addDecl(func_decl); @@ -7651,7 +7666,7 @@ TypeSystemClang::CreateParameterDeclarations( clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_clang_type, + llvm::StringRef asm_label, const CompilerType &method_clang_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial) { if (!type || !method_clang_type.IsValid() || name.empty()) @@ -7784,10 +7799,9 @@ clang::CXXMethodDecl *TypeSystemClang::AddMethodToCXXRecordType( if (is_attr_used) cxx_method_decl->addAttr(clang::UsedAttr::CreateImplicit(getASTContext())); - if (mangled_name != nullptr) { + if (!asm_label.empty()) cxx_method_decl->addAttr(clang::AsmLabelAttr::CreateImplicit( - getASTContext(), mangled_name, /*literal=*/false)); - } + getASTContext(), asm_label, /*literal=*/true)); // Parameters on member function declarations in DWARF generally don't // have names, so we omit them when creating the ParmVarDecls. diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h index 63dee9d..de66bb68 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h @@ -477,7 +477,7 @@ public: clang::FunctionDecl *CreateFunctionDeclaration( clang::DeclContext *decl_ctx, OptionalClangModuleID owning_module, llvm::StringRef name, const CompilerType &function_Type, - clang::StorageClass storage, bool is_inline); + clang::StorageClass storage, bool is_inline, llvm::StringRef asm_label); CompilerType CreateFunctionType(const CompilerType &result_type, @@ -1001,7 +1001,7 @@ public: clang::CXXMethodDecl *AddMethodToCXXRecordType( lldb::opaque_compiler_type_t type, llvm::StringRef name, - const char *mangled_name, const CompilerType &method_type, + llvm::StringRef asm_label, const CompilerType &method_type, lldb::AccessType access, bool is_virtual, bool is_static, bool is_inline, bool is_explicit, bool is_attr_used, bool is_artificial); diff --git a/lldb/source/Target/InstrumentationRuntime.cpp b/lldb/source/Target/InstrumentationRuntime.cpp index d5a2e2e..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,11 +62,11 @@ 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; }); } 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/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/Utility/WasmVirtualRegisters.h b/lldb/source/Utility/WasmVirtualRegisters.h new file mode 100644 index 0000000..404a5ae --- /dev/null +++ b/lldb/source/Utility/WasmVirtualRegisters.h @@ -0,0 +1,53 @@ +//===----------------------------------------------------------------------===// +// +// 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_UTILITY_WASM_VIRTUAL_REGISTERS_H +#define LLDB_SOURCE_UTILITY_WASM_VIRTUAL_REGISTERS_H + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// LLDB doesn't have an address space to represents WebAssembly locals, +// globals and operand stacks. We encode these elements into virtual +// registers: +// +// | tag: 2 bits | index: 30 bits | +// +// Where tag is: +// 0: Not a Wasm location +// 1: Local +// 2: Global +// 3: Operand stack value +enum WasmVirtualRegisterKinds { + eWasmTagNotAWasmLocation = 0, + eWasmTagLocal = 1, + eWasmTagGlobal = 2, + eWasmTagOperandStack = 3, +}; + +static const uint32_t kWasmVirtualRegisterTagMask = 0x03; +static const uint32_t kWasmVirtualRegisterIndexMask = 0x3fffffff; +static const uint32_t kWasmVirtualRegisterTagShift = 30; + +inline uint32_t GetWasmVirtualRegisterTag(size_t reg) { + return (reg >> kWasmVirtualRegisterTagShift) & kWasmVirtualRegisterTagMask; +} + +inline uint32_t GetWasmVirtualRegisterIndex(size_t reg) { + return reg & kWasmVirtualRegisterIndexMask; +} + +inline uint32_t GetWasmRegister(uint8_t tag, uint32_t index) { + return ((tag & kWasmVirtualRegisterTagMask) << kWasmVirtualRegisterTagShift) | + (index & kWasmVirtualRegisterIndexMask); +} + +} // namespace lldb_private + +#endif diff --git a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py index 1b21fe3..a488276 100644 --- a/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/array/TestArrayFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/basic/TestImportStdModule.py b/lldb/test/API/commands/expression/import-std-module/basic/TestImportStdModule.py index 0632328..0c242d5 100644 --- a/lldb/test/API/commands/expression/import-std-module/basic/TestImportStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/basic/TestImportStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class ImportStdModule(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) def test(self): self.build() @@ -38,6 +39,7 @@ class ImportStdModule(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) def test_non_cpp_language(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py b/lldb/test/API/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py index 95953de..b3241aa 100644 --- a/lldb/test/API/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py +++ b/lldb/test/API/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py @@ -15,6 +15,7 @@ from lldbsuite.test import lldbutil class TestImportStdModuleConflicts(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py index cfc480a..38b8508 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/deque-basic/TestDequeFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestBasicDeque(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py index 06f47e5..85eaa8f 100644 --- a/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDequeFromStdModule.py @@ -11,6 +11,7 @@ class TestDbgInfoContentDeque(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "18.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardListFromStdModule.py index d69f0ac..a3a409d 100644 --- a/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardListFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestDbgInfoContentForwardList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py index e3ed8f8..c9f4a15 100644 --- a/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/forward_list/TestForwardListFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestBasicForwardList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/iterator/TestIteratorFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/iterator/TestIteratorFromStdModule.py index 190bc5f..5c82ac3 100644 --- a/lldb/test/API/commands/expression/import-std-module/iterator/TestIteratorFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/iterator/TestIteratorFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py index 67ea6c6..0ecc244 100644 --- a/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentListFromStdModule.py @@ -12,7 +12,7 @@ class TestDbgInfoContentList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "12.0"]) - @skipIf(macos_version=["<", "14.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py index 85158ee..f29f353 100644 --- a/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/list/TestListFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestBasicList(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/non-module-type-separation/TestNonModuleTypeSeparation.py b/lldb/test/API/commands/expression/import-std-module/non-module-type-separation/TestNonModuleTypeSeparation.py index 5558c86..5e0ab48 100644 --- a/lldb/test/API/commands/expression/import-std-module/non-module-type-separation/TestNonModuleTypeSeparation.py +++ b/lldb/test/API/commands/expression/import-std-module/non-module-type-separation/TestNonModuleTypeSeparation.py @@ -11,6 +11,7 @@ from lldbsuite.test import lldbutil class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): """ diff --git a/lldb/test/API/commands/expression/import-std-module/retry-with-std-module/TestRetryWithStdModule.py b/lldb/test/API/commands/expression/import-std-module/retry-with-std-module/TestRetryWithStdModule.py index aa8646b..d003558 100644 --- a/lldb/test/API/commands/expression/import-std-module/retry-with-std-module/TestRetryWithStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/retry-with-std-module/TestRetryWithStdModule.py @@ -6,6 +6,7 @@ from lldbsuite.test import lldbutil class TestCase(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContentFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContentFromStdModule.py index 85755a6..50419b6 100644 --- a/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContentFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContentFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestSharedPtrDbgInfoContent(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/shared_ptr/TestSharedPtrFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/shared_ptr/TestSharedPtrFromStdModule.py index 35d62ae5..9f04361 100644 --- a/lldb/test/API/commands/expression/import-std-module/shared_ptr/TestSharedPtrFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/shared_ptr/TestSharedPtrFromStdModule.py @@ -11,6 +11,7 @@ class TestSharedPtr(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "17.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py b/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py index e21a4cc..39b720b 100644 --- a/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py +++ b/lldb/test/API/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py @@ -11,6 +11,7 @@ class TestUniquePtrDbgInfoContent(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "9.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipIfLinux # s.reset() causes link errors on ubuntu 18.04/Clang 9 def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/unique_ptr/TestUniquePtrFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/unique_ptr/TestUniquePtrFromStdModule.py index 2952b2e..90384d5 100644 --- a/lldb/test/API/commands/expression/import-std-module/unique_ptr/TestUniquePtrFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/unique_ptr/TestUniquePtrFromStdModule.py @@ -11,6 +11,7 @@ class TestUniquePtr(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "9.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipIfLinux # s.reset() causes link errors on ubuntu 18.04/Clang 9 def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectorsFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectorsFromStdModule.py index 5a168aa..6fa9dd5 100644 --- a/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectorsFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectorsFromStdModule.py @@ -10,6 +10,7 @@ from lldbsuite.test import lldbutil class TestVectorOfVectors(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtrFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtrFromStdModule.py index e95214d..19d24c1 100644 --- a/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtrFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtrFromStdModule.py @@ -11,6 +11,7 @@ class TestDbgInfoContentWeakPtr(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "17.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() diff --git a/lldb/test/API/commands/expression/import-std-module/weak_ptr/TestWeakPtrFromStdModule.py b/lldb/test/API/commands/expression/import-std-module/weak_ptr/TestWeakPtrFromStdModule.py index 0bc0fd4..e3cc9b9 100644 --- a/lldb/test/API/commands/expression/import-std-module/weak_ptr/TestWeakPtrFromStdModule.py +++ b/lldb/test/API/commands/expression/import-std-module/weak_ptr/TestWeakPtrFromStdModule.py @@ -11,6 +11,7 @@ class TestSharedPtr(TestBase): @add_test_categories(["libc++"]) @skipIf(compiler=no_match("clang")) @skipIf(compiler="clang", compiler_version=["<", "17.0"]) + @skipIf(macos_version=["<", "15.0"]) @skipUnlessDarwin def test(self): self.build() 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/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..73c81ef 100644 --- a/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py +++ b/lldb/test/API/functionalities/gdb_remote_client/TestWasm.py @@ -1,12 +1,14 @@ import lldb +import os import binascii from lldbsuite.test.lldbtest import * from lldbsuite.test.decorators import * from lldbsuite.test.gdbclientutils import * from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase -LLDB_INVALID_ADDRESS = lldb.LLDB_INVALID_ADDRESS -load_address = 0x400000000 +MODULE_ID = 4 +LOAD_ADDRESS = MODULE_ID << 32 +WASM_LOCAL_ADDR = 0x103E0 def format_register_value(val): @@ -24,17 +26,68 @@ def format_register_value(val): return result +class WasmStackFrame: + def __init__(self, address): + self._address = address + + def __str__(self): + return format_register_value(LOAD_ADDRESS | self._address) + + +class WasmCallStack: + def __init__(self, wasm_stack_frames): + self._wasm_stack_frames = wasm_stack_frames + + def __str__(self): + result = "" + for frame in self._wasm_stack_frames: + result += str(frame) + return result + + +class FakeMemory: + def __init__(self, start_addr, end_addr): + self._base_addr = start_addr + self._memory = bytearray(end_addr - start_addr) + self._memoryview = memoryview(self._memory) + + def store_bytes(self, addr, bytes_obj): + assert addr > self._base_addr + assert addr < self._base_addr + len(self._memoryview) + offset = addr - self._base_addr + chunk = self._memoryview[offset : offset + len(bytes_obj)] + for i in range(len(bytes_obj)): + chunk[i] = bytes_obj[i] + + def get_bytes(self, addr, length): + assert addr > self._base_addr + assert addr < self._base_addr + len(self._memoryview) + + offset = addr - self._base_addr + return self._memoryview[offset : offset + length] + + def contains(self, addr): + return addr - self._base_addr < len(self._memoryview) + + class MyResponder(MockGDBServerResponder): - current_pc = load_address + 0x0A + current_pc = LOAD_ADDRESS | 0x01AD - def __init__(self, obj_path, module_name=""): + def __init__(self, obj_path, module_name="", wasm_call_stacks=[], memory=None): self._obj_path = obj_path self._module_name = module_name or obj_path + self._wasm_call_stacks = wasm_call_stacks + self._call_stack_request_count = 0 + self._memory = memory MockGDBServerResponder.__init__(self) def respond(self, packet): if packet[0:13] == "qRegisterInfo": return self.qRegisterInfo(packet[13:]) + if packet.startswith("qWasmCallStack"): + return self.qWasmCallStack() + if packet.startswith("qWasmLocal"): + return self.qWasmLocal(packet) return MockGDBServerResponder.respond(self, packet) def qSupported(self, client_supported): @@ -47,7 +100,7 @@ class MyResponder(MockGDBServerResponder): return "" def qfThreadInfo(self): - return "OK" + return "m1," def qRegisterInfo(self, index): if index == 0: @@ -61,7 +114,7 @@ class MyResponder(MockGDBServerResponder): ) def haltReason(self): - return "T05thread:1;" + return "T02thread:1;" def readRegister(self, register): return format_register_value(self.current_pc) @@ -70,25 +123,62 @@ class MyResponder(MockGDBServerResponder): if obj == "libraries": xml = ( '<library-list><library name="%s"><section address="%d"/></library></library-list>' - % (self._module_name, load_address) + % (self._module_name, LOAD_ADDRESS) ) return xml, False else: return None, False def readMemory(self, addr, length): - if addr < load_address: + if self._memory and self._memory.contains(addr): + chunk = self._memory.get_bytes(addr, length) + return chunk.hex() + if addr < LOAD_ADDRESS: return "E02" result = "" with open(self._obj_path, mode="rb") as file: file_content = bytearray(file.read()) - addr_from = addr - load_address + if addr >= LOAD_ADDRESS + len(file_content): + return "E03" + addr_from = addr - LOAD_ADDRESS addr_to = addr_from + min(length, len(file_content) - addr_from) for i in range(addr_from, addr_to): result += format(file_content[i], "02x") file.close() return result + def setBreakpoint(self, packet): + bp_data = packet[1:].split(",") + self._bp_address = bp_data[1] + return "OK" + + def qfThreadInfo(self): + return "m1" + + def cont(self): + # Continue execution. Simulates running the Wasm engine until a breakpoint is hit. + return ( + "T05thread-pcs:" + + format(int(self._bp_address, 16) & 0x3FFFFFFFFFFFFFFF, "x") + + ";thread:1" + ) + + def qWasmCallStack(self): + if len(self._wasm_call_stacks) == 0: + return "" + result = str(self._wasm_call_stacks[self._call_stack_request_count]) + self._call_stack_request_count += 1 + return result + + def qWasmLocal(self, packet): + # Format: qWasmLocal:frame_index;index + data = packet.split(":") + data = data[1].split(";") + frame_index, local_index = data + if frame_index == "0" and local_index == "2": + return format_register_value(WASM_LOCAL_ADDR) + return "E03" + class TestWasm(GDBRemoteTestBase): @skipIfAsan @@ -104,7 +194,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] ) @@ -119,35 +209,35 @@ class TestWasm(GDBRemoteTestBase): code_section = module.GetSectionAtIndex(0) self.assertEqual("code", code_section.GetName()) self.assertEqual( - load_address | code_section.GetFileOffset(), + LOAD_ADDRESS | code_section.GetFileOffset(), code_section.GetLoadAddress(target), ) debug_info_section = module.GetSectionAtIndex(1) self.assertEqual(".debug_info", debug_info_section.GetName()) self.assertEqual( - load_address | debug_info_section.GetFileOffset(), + LOAD_ADDRESS | debug_info_section.GetFileOffset(), debug_info_section.GetLoadAddress(target), ) debug_abbrev_section = module.GetSectionAtIndex(2) self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName()) self.assertEqual( - load_address | debug_abbrev_section.GetFileOffset(), + LOAD_ADDRESS | debug_abbrev_section.GetFileOffset(), debug_abbrev_section.GetLoadAddress(target), ) debug_line_section = module.GetSectionAtIndex(3) self.assertEqual(".debug_line", debug_line_section.GetName()) self.assertEqual( - load_address | debug_line_section.GetFileOffset(), + LOAD_ADDRESS | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target), ) debug_str_section = module.GetSectionAtIndex(4) self.assertEqual(".debug_str", debug_str_section.GetName()) self.assertEqual( - load_address | debug_line_section.GetFileOffset(), + LOAD_ADDRESS | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target), ) @@ -174,7 +264,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] ) @@ -189,86 +279,103 @@ class TestWasm(GDBRemoteTestBase): code_section = module.GetSectionAtIndex(0) self.assertEqual("code", code_section.GetName()) self.assertEqual( - load_address | code_section.GetFileOffset(), + LOAD_ADDRESS | code_section.GetFileOffset(), code_section.GetLoadAddress(target), ) debug_info_section = module.GetSectionAtIndex(1) self.assertEqual(".debug_info", debug_info_section.GetName()) self.assertEqual( - LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target) + lldb.LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target) ) debug_abbrev_section = module.GetSectionAtIndex(2) self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName()) self.assertEqual( - LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target) + lldb.LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target) ) debug_line_section = module.GetSectionAtIndex(3) self.assertEqual(".debug_line", debug_line_section.GetName()) self.assertEqual( - LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) + lldb.LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) ) debug_str_section = module.GetSectionAtIndex(4) self.assertEqual(".debug_str", debug_str_section.GetName()) self.assertEqual( - LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) + lldb.LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) ) @skipIfAsan @skipIfXmlSupportMissing - def test_load_module_from_file(self): - """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module from a file""" - - yaml_path = "test_wasm_embedded_debug_sections.yaml" - yaml_base, ext = os.path.splitext(yaml_path) + def test_simple_wasm_debugging_session(self): + """Test connecting to a WebAssembly engine via GDB-remote, loading a + Wasm module with embedded DWARF symbols, setting a breakpoint and + checking the debuggee state""" + + # simple.yaml was created by compiling simple.c to wasm and using + # obj2yaml on the output. + # + # $ clang -target wasm32 -nostdlib -Wl,--no-entry -Wl,--export-all -O0 -g -o simple.wasm simple.c + # $ obj2yaml simple.wasm -o simple.yaml + yaml_path = "simple.yaml" + yaml_base, _ = os.path.splitext(yaml_path) obj_path = self.getBuildArtifact(yaml_base) self.yaml2obj(yaml_path, obj_path) - self.server.responder = MyResponder(obj_path) + # Create a fake call stack. + call_stacks = [ + WasmCallStack( + [WasmStackFrame(0x019C), WasmStackFrame(0x01E5), WasmStackFrame(0x01FE)] + ), + ] + + # Create fake memory for our wasm locals. + self.memory = FakeMemory(0x10000, 0x20000) + self.memory.store_bytes( + WASM_LOCAL_ADDR, + bytes.fromhex( + "0000000000000000020000000100000000000000020000000100000000000000" + ), + ) + + self.server.responder = MyResponder( + obj_path, "test_wasm", call_stacks, self.memory + ) target = self.dbg.CreateTarget("") - process = self.connect(target) + breakpoint = target.BreakpointCreateByName("add") + process = self.connect(target, "wasm") lldbutil.expect_state_changes( self, self.dbg.GetListener(), process, [lldb.eStateStopped] ) + location = breakpoint.GetLocationAtIndex(0) + self.assertTrue(location and location.IsEnabled(), VALID_BREAKPOINT_LOCATION) + num_modules = target.GetNumModules() self.assertEqual(1, num_modules) - module = target.GetModuleAtIndex(0) - num_sections = module.GetNumSections() - self.assertEqual(5, num_sections) + thread = process.GetThreadAtIndex(0) + self.assertTrue(thread.IsValid()) - code_section = module.GetSectionAtIndex(0) - self.assertEqual("code", code_section.GetName()) - self.assertEqual( - load_address | code_section.GetFileOffset(), - code_section.GetLoadAddress(target), - ) + # Check that our frames match our fake call stack. + frame0 = thread.GetFrameAtIndex(0) + self.assertTrue(frame0.IsValid()) + self.assertEqual(frame0.GetPC(), LOAD_ADDRESS | 0x019C) + self.assertIn("add", frame0.GetFunctionName()) - debug_info_section = module.GetSectionAtIndex(1) - self.assertEqual(".debug_info", debug_info_section.GetName()) - self.assertEqual( - LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target) - ) + frame1 = thread.GetFrameAtIndex(1) + self.assertTrue(frame1.IsValid()) + self.assertEqual(frame1.GetPC(), LOAD_ADDRESS | 0x01E5) + self.assertIn("main", frame1.GetFunctionName()) - debug_abbrev_section = module.GetSectionAtIndex(2) - self.assertEqual(".debug_abbrev", debug_abbrev_section.GetName()) - self.assertEqual( - LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target) - ) + # Check that we can resolve local variables. + a = frame0.FindVariable("a") + self.assertTrue(a.IsValid()) + self.assertEqual(a.GetValueAsUnsigned(), 1) - debug_line_section = module.GetSectionAtIndex(3) - self.assertEqual(".debug_line", debug_line_section.GetName()) - self.assertEqual( - LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) - ) - - debug_str_section = module.GetSectionAtIndex(4) - self.assertEqual(".debug_str", debug_str_section.GetName()) - self.assertEqual( - LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target) - ) + b = frame0.FindVariable("b") + self.assertTrue(b.IsValid()) + self.assertEqual(b.GetValueAsUnsigned(), 2) diff --git a/lldb/test/API/functionalities/gdb_remote_client/simple.c b/lldb/test/API/functionalities/gdb_remote_client/simple.c new file mode 100644 index 0000000..62ca1fe --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/simple.c @@ -0,0 +1,10 @@ +int add(int a, int b) { + // Break here + return a + b; +} + +int main() { + int i = 1; + int j = 2; + return add(i, j); +} diff --git a/lldb/test/API/functionalities/gdb_remote_client/simple.yaml b/lldb/test/API/functionalities/gdb_remote_client/simple.yaml new file mode 100644 index 0000000..cf1b7d8 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/simple.yaml @@ -0,0 +1,228 @@ +--- !WASM +FileHeader: + Version: 0x1 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: [] + ReturnTypes: [] + - Index: 1 + ParamTypes: + - I32 + - I32 + ReturnTypes: + - I32 + - Index: 2 + ParamTypes: [] + ReturnTypes: + - I32 + - Type: FUNCTION + FunctionTypes: [ 0, 1, 2, 1 ] + - Type: TABLE + Tables: + - Index: 0 + ElemType: FUNCREF + Limits: + Flags: [ HAS_MAX ] + Minimum: 0x1 + Maximum: 0x1 + - Type: MEMORY + Memories: + - Minimum: 0x2 + - Type: GLOBAL + Globals: + - Index: 0 + Type: I32 + Mutable: true + InitExpr: + Opcode: I32_CONST + Value: 66560 + - Index: 1 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1024 + - Index: 2 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1024 + - Index: 3 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1024 + - Index: 4 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 66560 + - Index: 5 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1024 + - Index: 6 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 66560 + - Index: 7 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 131072 + - Index: 8 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 0 + - Index: 9 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 1 + - Index: 10 + Type: I32 + Mutable: false + InitExpr: + Opcode: I32_CONST + Value: 65536 + - Type: EXPORT + Exports: + - Name: memory + Kind: MEMORY + Index: 0 + - Name: __wasm_call_ctors + Kind: FUNCTION + Index: 0 + - Name: add + Kind: FUNCTION + Index: 1 + - Name: __original_main + Kind: FUNCTION + Index: 2 + - Name: main + Kind: FUNCTION + Index: 3 + - Name: __main_void + Kind: FUNCTION + Index: 2 + - Name: __indirect_function_table + Kind: TABLE + Index: 0 + - Name: __dso_handle + Kind: GLOBAL + Index: 1 + - Name: __data_end + Kind: GLOBAL + Index: 2 + - Name: __stack_low + Kind: GLOBAL + Index: 3 + - Name: __stack_high + Kind: GLOBAL + Index: 4 + - Name: __global_base + Kind: GLOBAL + Index: 5 + - Name: __heap_base + Kind: GLOBAL + Index: 6 + - Name: __heap_end + Kind: GLOBAL + Index: 7 + - Name: __memory_base + Kind: GLOBAL + Index: 8 + - Name: __table_base + Kind: GLOBAL + Index: 9 + - Name: __wasm_first_page_end + Kind: GLOBAL + Index: 10 + - Type: CODE + Functions: + - Index: 0 + Locals: [] + Body: 0B + - Index: 1 + Locals: + - Type: I32 + Count: 1 + Body: 23808080800041106B21022002200036020C20022001360208200228020C20022802086A0F0B + - Index: 2 + Locals: + - Type: I32 + Count: 2 + Body: 23808080800041106B210020002480808080002000410036020C2000410136020820004102360204200028020820002802041081808080002101200041106A24808080800020010F0B + - Index: 3 + Locals: [] + Body: 1082808080000F0B + - Type: CUSTOM + Name: .debug_abbrev + Payload: 011101250E1305030E10171B0E110155170000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042E01110112064018030E3A0B3B0B49133F1900000534000218030E3A0B3B0B49130000062400030E3E0B0B0B000000 + - Type: CUSTOM + Name: .debug_info + Payload: 940000000400000000000401620000001D0055000000000000000D000000000000000000000002050000002900000004ED00029F510000000101900000000302910C60000000010190000000030291085E00000001019000000000042F0000004C00000004ED00009F04000000010690000000050291080B0000000107900000000502910409000000010890000000000600000000050400 + - Type: CUSTOM + Name: .debug_ranges + Payload: 050000002E0000002F0000007B0000000000000000000000 + - Type: CUSTOM + Name: .debug_str + Payload: 696E74006D61696E006A0069002F55736572732F6A6F6E61732F7761736D2D6D6963726F2D72756E74696D652F70726F647563742D6D696E692F706C6174666F726D732F64617277696E2F6275696C64006164640073696D706C652E630062006100636C616E672076657273696F6E2032322E302E306769742028676974406769746875622E636F6D3A4A4465766C696567686572652F6C6C766D2D70726F6A6563742E67697420343161363839613132323834633834623632383933393461356338306264636534383733656466302900 + - Type: CUSTOM + Name: .debug_line + Payload: 62000000040020000000010101FB0E0D0001010101000000010000010073696D706C652E6300000000000005020500000001050A0A08AE050E0658050C5805032002020001010005022F0000001705070A08BB75050E7505110658050A58050382020F000101 + - Type: CUSTOM + Name: name + FunctionNames: + - Index: 0 + Name: __wasm_call_ctors + - Index: 1 + Name: add + - Index: 2 + Name: __original_main + - Index: 3 + Name: main + GlobalNames: + - Index: 0 + Name: __stack_pointer + - Type: CUSTOM + Name: producers + Languages: + - Name: C11 + Version: '' + Tools: + - Name: clang + Version: '22.0.0git' + - Type: CUSTOM + Name: target_features + Features: + - Prefix: USED + Name: bulk-memory + - Prefix: USED + Name: bulk-memory-opt + - Prefix: USED + Name: call-indirect-overlong + - Prefix: USED + Name: multivalue + - Prefix: USED + Name: mutable-globals + - Prefix: USED + Name: nontrapping-fptoint + - Prefix: USED + Name: reference-types + - Prefix: USED + Name: sign-ext +... diff --git a/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py b/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py index dd03a0c..9dfc685 100644 --- a/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py +++ b/lldb/test/API/functionalities/postmortem/elf-core/expr/TestExpr.py @@ -37,6 +37,10 @@ class CoreExprTestCase(TestBase): self.target.EvaluateExpression("int $my_int = 5") self.expect_expr("$my_int * 2", result_type="int", result_value="10") + # Try assigning the persistent variable a new value. + self.target.EvaluateExpression("$my_int = 55") + self.expect_expr("$my_int", result_type="int", result_value="55") + def test_context_object(self): """Test expression evaluation in context of an object.""" 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 Binary files differindex 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 diff --git a/lldb/test/API/linux/aarch64/mte_core_file/core.nomte b/lldb/test/API/linux/aarch64/mte_core_file/core.nomte Binary files differindex 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 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/Shell/Commands/command-disassemble-process.yaml b/lldb/test/Shell/Commands/command-disassemble-process.yaml index ce1b37b..931e0b9 100644 --- a/lldb/test/Shell/Commands/command-disassemble-process.yaml +++ b/lldb/test/Shell/Commands/command-disassemble-process.yaml @@ -1,19 +1,20 @@ # REQUIRES: x86 -# RUN: yaml2obj --docnum=1 -DMAIN_SIZE=8 %s -o %T/command-disassemble-process.exe -# RUN: yaml2obj --docnum=1 -DMAIN_SIZE=8000 %s -o %T/command-disassemble-process.big.exe +# RUN: mkdir -p %t.dir +# RUN: yaml2obj --docnum=1 -DMAIN_SIZE=8 %s -o %t.dir/command-disassemble-process.exe +# RUN: yaml2obj --docnum=1 -DMAIN_SIZE=8000 %s -o %t.dir/command-disassemble-process.big.exe # RUN: yaml2obj --docnum=2 %s -o %t -# RUN: %lldb -c %t %T/command-disassemble-process.exe \ +# RUN: %lldb -c %t %t.dir/command-disassemble-process.exe \ # RUN: -o "settings set interpreter.stop-command-source-on-error false" \ # RUN: -s %S/Inputs/command-disassemble-process.lldbinit -o exit \ # RUN: | FileCheck %s -# RUN: %lldb -c %t %T/command-disassemble-process.big.exe \ +# RUN: %lldb -c %t %t.dir/command-disassemble-process.big.exe \ # RUN: -o "settings set stop-disassembly-max-size 8000" \ # RUN: -o disassemble -o exit 2>&1 | FileCheck %s --check-prefix=BIG -# RUN: %lldb -c %t %T/command-disassemble-process.exe \ +# RUN: %lldb -c %t %t.dir/command-disassemble-process.exe \ # RUN: -o "settings set interpreter.stop-command-source-on-error false" \ # RUN: -o "disassemble --address 0xdead" -o exit 2>&1 \ # RUN: | FileCheck %s --check-prefix=INVALID diff --git a/lldb/test/Shell/Commands/command-image-lookup.yaml b/lldb/test/Shell/Commands/command-image-lookup.yaml index cf7be93..fc12b99 100644 --- a/lldb/test/Shell/Commands/command-image-lookup.yaml +++ b/lldb/test/Shell/Commands/command-image-lookup.yaml @@ -1,7 +1,8 @@ -# RUN: yaml2obj %s -o %T/a.out -# RUN: %lldb %T/a.out -o "image lookup --verbose --address 0x0000000100003fa1" -o exit | FileCheck %s --check-prefix=NOINLINE -# RUN: %lldb %T/a.out -o "image lookup --verbose --address 0x0000000100003fa2" -o exit | FileCheck %s --check-prefix=INLINE_1 -# RUN: %lldb %T/a.out -o "image lookup --verbose --address 0x0000000100003fa8" -o exit | FileCheck %s --check-prefix=INLINE_2 +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %s -o %t.dir/a.out +# RUN: %lldb %t.dir/a.out -o "image lookup --verbose --address 0x0000000100003fa1" -o exit | FileCheck %s --check-prefix=NOINLINE +# RUN: %lldb %t.dir/a.out -o "image lookup --verbose --address 0x0000000100003fa2" -o exit | FileCheck %s --check-prefix=INLINE_1 +# RUN: %lldb %t.dir/a.out -o "image lookup --verbose --address 0x0000000100003fa8" -o exit | FileCheck %s --check-prefix=INLINE_2 # NOINLINE: Summary: a.out`main + 33 at main.cpp:10 # NOINLINE-NEXT: Module: file = diff --git a/lldb/test/Shell/Minidump/Windows/arm-fp-unwind.test b/lldb/test/Shell/Minidump/Windows/arm-fp-unwind.test index 7c056b6..ec70027 100644 --- a/lldb/test/Shell/Minidump/Windows/arm-fp-unwind.test +++ b/lldb/test/Shell/Minidump/Windows/arm-fp-unwind.test @@ -2,10 +2,11 @@ Test that unwind plans use the frame pointer register correctly. REQUIRES: arm -RUN: yaml2obj %S/Inputs/arm-fp-unwind.exe.yaml -o %T/arm-fp-unwind.exe -RUN: yaml2obj %S/Inputs/arm-fp-unwind.dmp.yaml -o %T/arm-fp-unwind.dmp -RUN: %lldb -O "settings set target.exec-search-paths %T" \ -RUN: -c %T/arm-fp-unwind.dmp -o "image show-unwind -a 0x00c71010" -b \ +RUN: mkdir -p %t.dir +RUN: yaml2obj %S/Inputs/arm-fp-unwind.exe.yaml -o %t.dir/arm-fp-unwind.exe +RUN: yaml2obj %S/Inputs/arm-fp-unwind.dmp.yaml -o %t.dir/arm-fp-unwind.dmp +RUN: %lldb -O "settings set target.exec-search-paths %t.dir" \ +RUN: -c %t.dir/arm-fp-unwind.dmp -o "image show-unwind -a 0x00c71010" -b \ RUN: | FileCheck %s CHECK: Assembly language inspection UnwindPlan: diff --git a/lldb/test/Shell/Minidump/Windows/broken-unwind.test b/lldb/test/Shell/Minidump/Windows/broken-unwind.test index 464624b..d8e1866 100644 --- a/lldb/test/Shell/Minidump/Windows/broken-unwind.test +++ b/lldb/test/Shell/Minidump/Windows/broken-unwind.test @@ -1,7 +1,8 @@ Test that we can cope with broken unwind information that suggests reading out of bounds. -RUN: yaml2obj %S/Inputs/broken-unwind.exe.yaml -o %T/broken-unwind.exe -RUN: yaml2obj %S/Inputs/broken-unwind.dmp.yaml -o %T/broken-unwind.dmp -RUN: %lldb -O "settings set target.exec-search-paths %T" \ -RUN: -c %T/broken-unwind.dmp -o "image show-unwind -a 0xb1000" -o exit +RUN: mkdir -p %t.dir +RUN: yaml2obj %S/Inputs/broken-unwind.exe.yaml -o %t.dir/broken-unwind.exe +RUN: yaml2obj %S/Inputs/broken-unwind.dmp.yaml -o %t.dir/broken-unwind.dmp +RUN: %lldb -O "settings set target.exec-search-paths %t.dir" \ +RUN: -c %t.dir/broken-unwind.dmp -o "image show-unwind -a 0xb1000" -o exit diff --git a/lldb/test/Shell/Minidump/Windows/find-module.test b/lldb/test/Shell/Minidump/Windows/find-module.test index 39d9dab..724d524 100644 --- a/lldb/test/Shell/Minidump/Windows/find-module.test +++ b/lldb/test/Shell/Minidump/Windows/find-module.test @@ -3,18 +3,19 @@ use it when opening minidumps. XFAIL: system-windows && remote-linux -RUN: yaml2obj %S/Inputs/find-module.exe.yaml -o %T/find-module.exe -RUN: yaml2obj %S/Inputs/find-module.dmp.yaml -o %T/find-module.dmp -RUN: %lldb -O "settings set target.exec-search-paths %T" \ -RUN: -c %T/find-module.dmp -o "image dump objfile" -o "target list" -o exit \ +RUN: mkdir -p %t.dir +RUN: yaml2obj %S/Inputs/find-module.exe.yaml -o %t.dir/find-module.exe +RUN: yaml2obj %S/Inputs/find-module.dmp.yaml -o %t.dir/find-module.dmp +RUN: %lldb -O "settings set target.exec-search-paths %t.dir" \ +RUN: -c %t.dir/find-module.dmp -o "image dump objfile" -o "target list" -o exit \ RUN: | FileCheck --check-prefix=DEFAULT %s RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi msvc" \ -RUN: -O "settings set target.exec-search-paths %T" -c %T/find-module.dmp \ +RUN: -O "settings set target.exec-search-paths %t.dir" -c %t.dir/find-module.dmp \ RUN: -o "target list" -o exit | FileCheck --check-prefix=MSVC %s RUN: %lldb -O "settings set plugin.object-file.pe-coff.abi gnu" \ -RUN: -O "settings set target.exec-search-paths %T" -c %T/find-module.dmp \ +RUN: -O "settings set target.exec-search-paths %t.dir" -c %t.dir/find-module.dmp \ RUN: -o "target list" -o exit | FileCheck --check-prefix=GNU %s DEFAULT-LABEL: image dump objfile diff --git a/lldb/test/Shell/Minidump/memory-region-from-module.yaml b/lldb/test/Shell/Minidump/memory-region-from-module.yaml index 3ebc03c..bc8c899 100644 --- a/lldb/test/Shell/Minidump/memory-region-from-module.yaml +++ b/lldb/test/Shell/Minidump/memory-region-from-module.yaml @@ -3,14 +3,14 @@ # RUN: yaml2obj --docnum=1 %s -o %t1.dmp # RUN: yaml2obj --docnum=2 %s -o %t2.dmp -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/memory-region-from-module.exe +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.memory-region-from-module.exe -# RUN: %lldb -b -c %t1.dmp %T/memory-region-from-module.exe \ +# RUN: %lldb -b -c %t1.dmp %t.memory-region-from-module.exe \ # RUN: -o "memory region 0" -o "memory region 0x4000" \ # RUN: -o "memory region 0x5000" -o "memory region 0x6000" \ # RUN: | FileCheck --check-prefix=ALL --check-prefix=CHECK1 %s -# RUN: %lldb -b -c %t2.dmp %T/memory-region-from-module.exe \ +# RUN: %lldb -b -c %t2.dmp %t.memory-region-from-module.exe \ # RUN: -o "memory region 0" -o "memory region 0x4000" \ # RUN: -o "memory region 0x5000" -o "memory region 0x6000" \ # RUN: | FileCheck --check-prefix=ALL --check-prefix=CHECK2 %s diff --git a/lldb/test/Shell/ObjectFile/Breakpad/uuid-matching-mac.test b/lldb/test/Shell/ObjectFile/Breakpad/uuid-matching-mac.test index f2dd2e5..26899ea 100644 --- a/lldb/test/Shell/ObjectFile/Breakpad/uuid-matching-mac.test +++ b/lldb/test/Shell/ObjectFile/Breakpad/uuid-matching-mac.test @@ -1,6 +1,7 @@ -# RUN: yaml2obj %S/Inputs/uuid-matching-mac.yaml -o %T/uuid-matching-mac.out +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/uuid-matching-mac.yaml -o %t.dir/uuid-matching-mac.out # RUN: cd %S -# RUN: %lldb %T/uuid-matching-mac.out -s %s -o exit | FileCheck %s +# RUN: %lldb %t.dir/uuid-matching-mac.out -s %s -o exit | FileCheck %s target symbols add Inputs/uuid-matching-mac.syms # CHECK-LABEL: target symbols add diff --git a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-set-and-hit-breakpoint.test b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-set-and-hit-breakpoint.test index a965061..0ffc51a 100644 --- a/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-set-and-hit-breakpoint.test +++ b/lldb/test/Shell/ObjectFile/ELF/minidebuginfo-set-and-hit-breakpoint.test @@ -2,8 +2,8 @@ # We want to keep the symbol "multiplyByThree" in the .dynamic section and not # have it put the default .symtab section. -# RUN: echo "{multiplyByThree;};" > %T/dynmic-symbols.txt -# RUN: %clang_host -Wl,--dynamic-list=%T/dynmic-symbols.txt -g -o %t.binary %p/Inputs/minidebuginfo-main.c +# RUN: echo "{multiplyByThree;};" > %t.dynmic-symbols.txt +# RUN: %clang_host -Wl,--dynamic-list=%t.dynmic-symbols.txt -g -o %t.binary %p/Inputs/minidebuginfo-main.c # The following section is adapted from GDB's official documentation: # http://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html#MiniDebugInfo diff --git a/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c b/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c new file mode 100644 index 0000000..9f12c32 --- /dev/null +++ b/lldb/test/Shell/Recognizer/Inputs/ubsan_add_overflow.c @@ -0,0 +1,3 @@ +#include <limits.h> + +int main() { return INT_MAX + 1; } diff --git a/lldb/test/Shell/Recognizer/ubsan_add_overflow.test b/lldb/test/Shell/Recognizer/ubsan_add_overflow.test new file mode 100644 index 0000000..9dac039 --- /dev/null +++ b/lldb/test/Shell/Recognizer/ubsan_add_overflow.test @@ -0,0 +1,20 @@ +# RUN: %clang_host -g -O0 %S/Inputs/ubsan_add_overflow.c -o %t.out \ +# RUN: -fsanitize=signed-integer-overflow -fsanitize-trap=signed-integer-overflow + +# RUN: %lldb -b -s %s %t.out | FileCheck %s + +run +# CHECK: thread #{{.*}} stop reason = Undefined Behavior Sanitizer: Integer addition overflowed +# CHECK-NEXT: frame #1: {{.*}}`main at ubsan_add_overflow.c + +bt +# CHECK: frame #0: {{.*}}`__clang_trap_msg$Undefined Behavior Sanitizer$Integer addition overflowed{{.*}} +# CHECK: frame #1: {{.*}}`main at ubsan_add_overflow.c + +frame info +# CHECK: frame #{{.*}}`main at ubsan_add_overflow.c + +frame recognizer info 0 +# CHECK: frame 0 is recognized by Verbose Trap StackFrame Recognizer + +quit
\ No newline at end of file diff --git a/lldb/test/Shell/Scripts/TestFrameworkFixScript.test b/lldb/test/Shell/Scripts/TestFrameworkFixScript.test index 2b1818e..183ea3a 100644 --- a/lldb/test/Shell/Scripts/TestFrameworkFixScript.test +++ b/lldb/test/Shell/Scripts/TestFrameworkFixScript.test @@ -1,6 +1,6 @@ # Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir. RUN: mkdir -p %t/Outputs -RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG +RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG # Check the output RUN: cat %t/Outputs/SBAddress.h | FileCheck %s diff --git a/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test b/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test index ba18b4b..a4fffe4 100644 --- a/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test +++ b/lldb/test/Shell/Scripts/TestFrameworkFixUnifdef.test @@ -1,7 +1,7 @@ # REQUIRES: system-darwin # Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir. RUN: mkdir -p %t/Outputs -RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG +RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_main -i %p/Inputs/Main/SBAddress.h -o %t/Outputs/SBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG # Check the output RUN: cat %t/Outputs/SBAddress.h | FileCheck %s diff --git a/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test b/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test index e2080ca..d7775c2 100644 --- a/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test +++ b/lldb/test/Shell/Scripts/TestRPCFrameworkFixScript.test @@ -1,6 +1,6 @@ # Create a temp dir for output and run the framework fix script on the truncated version of SBAddress.h in the inputs dir. RUN: mkdir -p %t/Outputs -RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_rpc -i %p/Inputs/RPC/RPCSBAddress.h -o %t/Outputs/RPCSBAddress.h -p /usr/bin/unifdef --unifdef_guards USWIG +RUN: %python %p/../../../scripts/framework-header-fix.py -f lldb_rpc -i %p/Inputs/RPC/RPCSBAddress.h -o %t/Outputs/RPCSBAddress.h -p /usr/bin/unifdef --unifdef_guards SWIG # Check the output RUN: cat %t/Outputs/RPCSBAddress.h | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/Breakpad/inline-record.test b/lldb/test/Shell/SymbolFile/Breakpad/inline-record.test index 280fc961..614a13b 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/inline-record.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/inline-record.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/inline-record.out -# RUN: %lldb %T/inline-record.out -o "target symbols add -s inline-record.out %S/Inputs/inline-record.syms" \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/inline-record.out +# RUN: %lldb %t.dir/inline-record.out -o "target symbols add -s inline-record.out %S/Inputs/inline-record.syms" \ # RUN: -s %s | FileCheck --match-full-lines %s # CHECK-LABEL: (lldb) image lookup -a 0x400010 -v diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table-discontinuous-file-ids.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table-discontinuous-file-ids.test index 0780cab..3b4e046 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table-discontinuous-file-ids.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table-discontinuous-file-ids.test @@ -1,7 +1,8 @@ # Test that we handle files which has gaps in the FILE record IDs. -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/line-table-discontinuous-file-ids.out -# RUN: %lldb %T/line-table-discontinuous-file-ids.out \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/line-table-discontinuous-file-ids.out +# RUN: %lldb %t.dir/line-table-discontinuous-file-ids.out \ # RUN: -o "target symbols add -s line-table-discontinuous-file-ids.out %S/Inputs/line-table-discontinuous-file-ids.syms" \ # RUN: -s %s -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table-edgecases.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table-edgecases.test index 805f280..f1c631f 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table-edgecases.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table-edgecases.test @@ -2,8 +2,9 @@ # input contains a LINE record which does not belong to any function as well as # a FUNC record without any LINE records. -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/line-table-edgecases.out -# RUN: %lldb %T/line-table-edgecases.out \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/line-table-edgecases.out +# RUN: %lldb %t.dir/line-table-edgecases.out \ # RUN: -o "target symbols add -s line-table-edgecases.out %S/Inputs/line-table-edgecases.syms" \ # RUN: -s %s -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table-missing-file.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table-missing-file.test index 1018d02..e9e1ef4 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table-missing-file.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table-missing-file.test @@ -3,8 +3,9 @@ # Right now, "something reasonable" means creating a line entry with an empty # file. -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/line-table-missing-file.out -# RUN: %lldb %T/line-table-missing-file.out \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/line-table-missing-file.out +# RUN: %lldb %t.dir/line-table-missing-file.out \ # RUN: -o "target symbols add -s line-table-missing-file.out %S/Inputs/line-table-missing-file.syms" \ # RUN: -s %s -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table-mixed-path-styles.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table-mixed-path-styles.test index cb3349f..c299c46 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table-mixed-path-styles.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table-mixed-path-styles.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/line-table-mixed-path-styles.out -# RUN: %lldb %T/line-table-mixed-path-styles.out \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/line-table-mixed-path-styles.out +# RUN: %lldb %t.dir/line-table-mixed-path-styles.out \ # RUN: -o "target symbols add -s line-table-mixed-path-styles.out %S/Inputs/line-table-mixed-path-styles.syms" \ # RUN: -s %s -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/Breakpad/line-table.test b/lldb/test/Shell/SymbolFile/Breakpad/line-table.test index 2099571..c0c6e90 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/line-table.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/line-table.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/line-table.out -# RUN: %lldb %T/line-table.out -o "target symbols add -s line-table.out %S/Inputs/line-table.syms" \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/line-table.out +# RUN: %lldb %t.dir/line-table.out -o "target symbols add -s line-table.out %S/Inputs/line-table.syms" \ # RUN: -s %s -o exit | FileCheck %s # We create a compile unit for each function. The compile unit name is the first diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab-macho.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab-macho.test index ebfc31c..90f3c53 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab-macho.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab-macho.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-macho.yaml -o %T/symtab-macho.out -# RUN: %lldb %T/symtab-macho.out -o "target symbols add %S/Inputs/symtab-macho.syms" \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-macho.yaml -o %t.dir/symtab-macho.out +# RUN: %lldb %t.dir/symtab-macho.out -o "target symbols add %S/Inputs/symtab-macho.syms" \ # RUN: -s %s | FileCheck %s image dump symtab symtab-macho.out diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test index 00e04eb3..5aedbb4 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab-sorted-by-size.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/symtab-sorted-by-size.out -# RUN: %lldb %T/symtab-sorted-by-size.out -o "target symbols add -s symtab-sorted-by-size.out %S/Inputs/symtab.syms" \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/symtab-sorted-by-size.out +# RUN: %lldb %t.dir/symtab-sorted-by-size.out -o "target symbols add -s symtab-sorted-by-size.out %S/Inputs/symtab.syms" \ # RUN: -s %s | FileCheck %s # CHECK: num_symbols = 4 (sorted by size): diff --git a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test index a32eb58..0187ba3 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/symtab.test +++ b/lldb/test/Shell/SymbolFile/Breakpad/symtab.test @@ -1,5 +1,6 @@ -# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %T/symtab.out -# RUN: %lldb %T/symtab.out -o "target symbols add -s symtab.out %S/Inputs/symtab.syms" \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj %S/Inputs/basic-elf.yaml -o %t.dir/symtab.out +# RUN: %lldb %t.dir/symtab.out -o "target symbols add -s symtab.out %S/Inputs/symtab.syms" \ # RUN: -s %s | FileCheck %s # CHECK-LABEL: (lldb) image dump symtab symtab.out diff --git a/lldb/test/Shell/SymbolFile/Breakpad/unwind-via-stack-win-no-memory-info.yaml b/lldb/test/Shell/SymbolFile/Breakpad/unwind-via-stack-win-no-memory-info.yaml index 8981c84..fbf7c14 100644 --- a/lldb/test/Shell/SymbolFile/Breakpad/unwind-via-stack-win-no-memory-info.yaml +++ b/lldb/test/Shell/SymbolFile/Breakpad/unwind-via-stack-win-no-memory-info.yaml @@ -1,8 +1,9 @@ # REQUIRES: x86 # RUN: yaml2obj --docnum=1 %s -o %t.dmp -# RUN: yaml2obj --docnum=2 %s -o %T/unwind-via-stack-win-no-memory-info.exe -# RUN: %lldb -c %t.dmp %T/unwind-via-stack-win-no-memory-info.exe \ +# RUN: mkdir -p %t.dir +# RUN: yaml2obj --docnum=2 %s -o %t.dir/unwind-via-stack-win-no-memory-info.exe +# RUN: %lldb -c %t.dmp %t.dir/unwind-via-stack-win-no-memory-info.exe \ # RUN: -o "target symbols add %S/Inputs/unwind-via-raSearch.syms" \ # RUN: -o "thread backtrace" -b | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-missing-error.test b/lldb/test/Shell/SymbolFile/DWARF/dwo-missing-error.test index 4f7e70e..2805bbb 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/dwo-missing-error.test +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-missing-error.test @@ -9,7 +9,6 @@ # Creating and compiling to %t.compdir makes it easy to remove the dwo files. # DW_AT_comp_dir should be "./a/b/", and DW_AT_dwo_name should be # "a.out-dwo-missing-error.dwo". -# since %T is deprecated. # RUN: rm -rf %t.compdir/ # RUN: mkdir -p %t.compdir/a/b/ # RUN: cd %t.compdir/a/b/ diff --git a/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-path.s b/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-path.s index f3d4457..2c9c584 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-path.s +++ b/lldb/test/Shell/SymbolFile/DWARF/dwo-relative-path.s @@ -3,12 +3,13 @@ # REQUIRES: x86 -# RUN: llvm-mc --filetype=obj --triple x86_64-pc-linux %s -o %t.o -# RUN: llvm-objcopy --split-dwo=%T/dwo-relative-path.dwo %t.o +# RUN: mkdir -p %t.dir +# RUN: llvm-mc --filetype=obj --triple x86_64-pc-linux %s -o %t.dir/obj.o +# RUN: llvm-objcopy --split-dwo=%t.dir/dwo-relative-path.dwo %t.dir/obj.o # RUN: cd ../.. -# RUN: %lldb %t.o -o "target var x" -b 2>&1 | FileCheck %s +# RUN: %lldb %t.dir/obj.o -o "target var x" -b 2>&1 | FileCheck %s # CHECK: x = 10 diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s index 393c045..b67c001 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_loclists-dwo.s @@ -1,4 +1,5 @@ -# RUN: cd %T +# RUN: mkdir -p %t.dir +# RUN: cd %t.dir # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s >debug_loclists-dwo.o # RUN: %lldb debug_loclists-dwo.o -o "image lookup -v -s lookup_loclists" -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_rnglists-dwo.s b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_rnglists-dwo.s index edc8345..7089be1 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/debug_rnglists-dwo.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/debug_rnglists-dwo.s @@ -1,4 +1,5 @@ -# RUN: cd %T +# RUN: mkdir -p %t.dir +# RUN: cd %t.dir # RUN: llvm-mc -triple=x86_64-pc-linux -filetype=obj %s >debug_rnglists-dwo.o # RUN: %lldb debug_rnglists-dwo.o -o "image lookup -v -s lookup_rnglists" \ # RUN: -o exit | FileCheck %s diff --git a/lldb/test/Shell/SymbolFile/DWARF/x86/dwo-type-in-main-file.s b/lldb/test/Shell/SymbolFile/DWARF/x86/dwo-type-in-main-file.s index 6c63912..5ef85b9f 100644 --- a/lldb/test/Shell/SymbolFile/DWARF/x86/dwo-type-in-main-file.s +++ b/lldb/test/Shell/SymbolFile/DWARF/x86/dwo-type-in-main-file.s @@ -2,10 +2,10 @@ # type, but that type is defined in another compile unit in the main object # file. -# RUN: llvm-mc %s -o %t --triple=x86_64-pc-linux --filetype=obj --defsym MAIN=0 -# RUN: llvm-mc %s -o %T/dwo-type-in-main-file-cu2.dwo --triple=x86_64-pc-linux --filetype=obj --defsym DWO=0 -# RUN: cd %T -# RUN: %lldb %t -o "target var a" -b 2>&1 | FileCheck %s +# RUN: mkdir -p %t.dir +# RUN: llvm-mc %s -o %t.dir/obj.o --triple=x86_64-pc-linux --filetype=obj --defsym MAIN=0 +# RUN: llvm-mc %s -o %t.dir/dwo-type-in-main-file-cu2.dwo --triple=x86_64-pc-linux --filetype=obj --defsym DWO=0 +# RUN: %lldb %t.dir/obj.o -o "target var a" -b 2>&1 | FileCheck %s # CHECK: (A) a = (b = 47) diff --git a/lldb/test/Shell/SymbolFile/PDB/class-layout.test b/lldb/test/Shell/SymbolFile/PDB/class-layout.test index efd52b8..e9a7d1c 100644 --- a/lldb/test/Shell/SymbolFile/PDB/class-layout.test +++ b/lldb/test/Shell/SymbolFile/PDB/class-layout.test @@ -1,16 +1,17 @@ REQUIRES: target-windows, msvc -RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/ClassLayoutTest.cpp.obj %S/Inputs/ClassLayoutTest.cpp -RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/ClassLayoutTest.cpp.exe %T/ClassLayoutTest.cpp.obj -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=ENUM %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNION %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=STRUCT %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=COMPLEX %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=LIST %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNNAMED-STRUCT %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=BASE %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=FRIEND %s -RUN: lldb-test symbols %T/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=CLASS %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%t.dir/ClassLayoutTest.cpp.obj %S/Inputs/ClassLayoutTest.cpp +RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%t.dir/ClassLayoutTest.cpp.exe %t.dir/ClassLayoutTest.cpp.obj +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=ENUM %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNION %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=STRUCT %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=COMPLEX %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=LIST %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=UNNAMED-STRUCT %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=BASE %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=FRIEND %s +RUN: lldb-test symbols %t.dir/ClassLayoutTest.cpp.exe | FileCheck --check-prefix=CLASS %s CHECK: Module [[MOD:.*]] CHECK: SymbolFile pdb ([[MOD]]) diff --git a/lldb/test/Shell/SymbolFile/PDB/compilands.test b/lldb/test/Shell/SymbolFile/PDB/compilands.test index 6ea9082..ed28256 100644 --- a/lldb/test/Shell/SymbolFile/PDB/compilands.test +++ b/lldb/test/Shell/SymbolFile/PDB/compilands.test @@ -1,8 +1,9 @@ REQUIRES: target-windows, msvc -RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/CompilandsTest.cpp.obj %S/Inputs/CompilandsTest.cpp -RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/CompilandsTest.cpp.exe %T/CompilandsTest.cpp.obj -RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %T/CompilandsTest.cpp.exe | FileCheck %s -RUN: lldb-test symbols %T/CompilandsTest.cpp.exe | FileCheck %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%t.dir/CompilandsTest.cpp.obj %S/Inputs/CompilandsTest.cpp +RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%t.dir/CompilandsTest.cpp.exe %t.dir/CompilandsTest.cpp.obj +RUN: env LLDB_USE_NATIVE_PDB_READER=1 lldb-test symbols %t.dir/CompilandsTest.cpp.exe | FileCheck %s +RUN: lldb-test symbols %t.dir/CompilandsTest.cpp.exe | FileCheck %s ; Link default libraries diff --git a/lldb/test/Shell/SymbolFile/PDB/enums-layout.test b/lldb/test/Shell/SymbolFile/PDB/enums-layout.test index ad7d154..6f861c6d 100644 --- a/lldb/test/Shell/SymbolFile/PDB/enums-layout.test +++ b/lldb/test/Shell/SymbolFile/PDB/enums-layout.test @@ -1,11 +1,12 @@ REQUIRES: system-windows, msvc -RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%T/SimpleTypesTest.cpp.enums.exe %S/Inputs/SimpleTypesTest.cpp -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM %s -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CONST-ENUM %s -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=EMPTY-ENUM %s -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=UCHAR-ENUM %s -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CLASS-ENUM %s -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=STRUCT-ENUM %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%t.dir/SimpleTypesTest.cpp.enums.exe %S/Inputs/SimpleTypesTest.cpp +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=ENUM %s +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CONST-ENUM %s +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=EMPTY-ENUM %s +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=UCHAR-ENUM %s +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=CLASS-ENUM %s +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.enums.exe | FileCheck --check-prefix=STRUCT-ENUM %s ; FIXME: PDB does not have information about scoped enumeration (Enum class) so the ; compiler type used is the same as the one for unscoped enumeration. diff --git a/lldb/test/Shell/SymbolFile/PDB/func-symbols.test b/lldb/test/Shell/SymbolFile/PDB/func-symbols.test index 95e0dd5e..408db14 100644 --- a/lldb/test/Shell/SymbolFile/PDB/func-symbols.test +++ b/lldb/test/Shell/SymbolFile/PDB/func-symbols.test @@ -1,7 +1,8 @@ REQUIRES: target-windows, lld -RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%T/FuncSymbolsTest.exe %S/Inputs/FuncSymbolsTestMain.cpp %S/Inputs/FuncSymbols.cpp -RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-ONE %s -RUN: lldb-test symbols %T/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-TWO %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%t.dir/FuncSymbolsTest.exe %S/Inputs/FuncSymbolsTestMain.cpp %S/Inputs/FuncSymbols.cpp +RUN: lldb-test symbols %t.dir/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-ONE %s +RUN: lldb-test symbols %t.dir/FuncSymbolsTest.exe | FileCheck --check-prefix=CHECK-TWO %s ; Link multiple objects ; In this test, We don't check demangled name of a mangled function. diff --git a/lldb/test/Shell/SymbolFile/PDB/pointers.test b/lldb/test/Shell/SymbolFile/PDB/pointers.test index 355b5fa..29fe171 100644 --- a/lldb/test/Shell/SymbolFile/PDB/pointers.test +++ b/lldb/test/Shell/SymbolFile/PDB/pointers.test @@ -1,11 +1,12 @@ REQUIRES: target-windows, msvc -RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/PointerTypeTest.cpp.obj %S/Inputs/PointerTypeTest.cpp -RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/PointerTypeTest.cpp.exe %T/PointerTypeTest.cpp.obj -RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck %s -RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST-F %s -RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST %s -RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN %s -RUN: lldb-test symbols %T/PointerTypeTest.cpp.exe | FileCheck --check-prefix=F %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%t.dir/PointerTypeTest.cpp.obj %S/Inputs/PointerTypeTest.cpp +RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%t.dir/PointerTypeTest.cpp.exe %t.dir/PointerTypeTest.cpp.obj +RUN: lldb-test symbols %t.dir/PointerTypeTest.cpp.exe | FileCheck %s +RUN: lldb-test symbols %t.dir/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST-F %s +RUN: lldb-test symbols %t.dir/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN-ST %s +RUN: lldb-test symbols %t.dir/PointerTypeTest.cpp.exe | FileCheck --check-prefix=MAIN %s +RUN: lldb-test symbols %t.dir/PointerTypeTest.cpp.exe | FileCheck --check-prefix=F %s CHECK: Module [[MOD:.*]] CHECK: {{^[0-9A-F]+}}: CompileUnit{{[{]0x[0-9a-f]+[}]}}, language = "c++", file = '{{.*}}\PointerTypeTest.cpp' diff --git a/lldb/test/Shell/SymbolFile/PDB/type-quals.test b/lldb/test/Shell/SymbolFile/PDB/type-quals.test index 982bb70..e0d79ac 100644 --- a/lldb/test/Shell/SymbolFile/PDB/type-quals.test +++ b/lldb/test/Shell/SymbolFile/PDB/type-quals.test @@ -1,7 +1,8 @@ REQUIRES: target-windows, msvc -RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%T/TypeQualsTest.cpp.obj %S/Inputs/TypeQualsTest.cpp -RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%T/TypeQualsTest.cpp.exe %T/TypeQualsTest.cpp.obj -RUN: lldb-test symbols %T/TypeQualsTest.cpp.exe | FileCheck %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --mode=compile --arch=32 --nodefaultlib --output=%t.dir/TypeQualsTest.cpp.obj %S/Inputs/TypeQualsTest.cpp +RUN: %build --compiler=msvc --mode=link --arch=32 --nodefaultlib --output=%t.dir/TypeQualsTest.cpp.exe %t.dir/TypeQualsTest.cpp.obj +RUN: lldb-test symbols %t.dir/TypeQualsTest.cpp.exe | FileCheck %s CHECK: Module [[MOD:.*]] CHECK-DAG: SymbolFile pdb ([[MOD]]) diff --git a/lldb/test/Shell/SymbolFile/PDB/typedefs.test b/lldb/test/Shell/SymbolFile/PDB/typedefs.test index ebbcc4b..86846fb 100644 --- a/lldb/test/Shell/SymbolFile/PDB/typedefs.test +++ b/lldb/test/Shell/SymbolFile/PDB/typedefs.test @@ -1,6 +1,7 @@ REQUIRES: system-windows, msvc -RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%T/SimpleTypesTest.cpp.typedefs.exe %S/Inputs/SimpleTypesTest.cpp -RUN: lldb-test symbols %T/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=msvc --arch=32 --nodefaultlib --output=%t.dir/SimpleTypesTest.cpp.typedefs.exe %S/Inputs/SimpleTypesTest.cpp +RUN: lldb-test symbols %t.dir/SimpleTypesTest.cpp.typedefs.exe | FileCheck %s ; Generate 32-bit target diff --git a/lldb/test/Shell/SymbolFile/PDB/variables.test b/lldb/test/Shell/SymbolFile/PDB/variables.test index 0043ebb..9ee10f7 100644 --- a/lldb/test/Shell/SymbolFile/PDB/variables.test +++ b/lldb/test/Shell/SymbolFile/PDB/variables.test @@ -1,12 +1,13 @@ REQUIRES: system-windows, msvc -RUN: %build --compiler=clang-cl --mode=compile --arch=64 --nodefaultlib --output=%T/VariablesTest.cpp.obj %S/Inputs/VariablesTest.cpp -RUN: %build --compiler=msvc --mode=link --arch=64 --nodefaultlib --output=%T/VariablesTest.cpp.exe %T/VariablesTest.cpp.obj -RUN: lldb-test symbols %T/VariablesTest.cpp.exe > %T/VariablesTest.out -RUN: FileCheck --check-prefix=GLOBALS --input-file=%T/VariablesTest.out %s -RUN: FileCheck --check-prefix=FUNC-F --input-file=%T/VariablesTest.out %s -RUN: FileCheck --check-prefix=FUNC-MAIN --input-file=%T/VariablesTest.out %s -RUN: FileCheck --check-prefix=FUNC-CONSTRUCTOR --input-file=%T/VariablesTest.out %s -RUN: FileCheck --check-prefix=FUNC-MEMBER --input-file=%T/VariablesTest.out %s +RUN: mkdir -p %t.dir +RUN: %build --compiler=clang-cl --mode=compile --arch=64 --nodefaultlib --output=%t.dir/VariablesTest.cpp.obj %S/Inputs/VariablesTest.cpp +RUN: %build --compiler=msvc --mode=link --arch=64 --nodefaultlib --output=%t.dir/VariablesTest.cpp.exe %t.dir/VariablesTest.cpp.obj +RUN: lldb-test symbols %t.dir/VariablesTest.cpp.exe > %t.dir/VariablesTest.out +RUN: FileCheck --check-prefix=GLOBALS --input-file=%t.dir/VariablesTest.out %s +RUN: FileCheck --check-prefix=FUNC-F --input-file=%t.dir/VariablesTest.out %s +RUN: FileCheck --check-prefix=FUNC-MAIN --input-file=%t.dir/VariablesTest.out %s +RUN: FileCheck --check-prefix=FUNC-CONSTRUCTOR --input-file=%t.dir/VariablesTest.out %s +RUN: FileCheck --check-prefix=FUNC-MEMBER --input-file=%t.dir/VariablesTest.out %s GLOBALS: Module [[MOD:.*]] GLOBALS: SymbolFile pdb ([[MOD]]) diff --git a/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake index 6c363f4..2376e23 100644 --- a/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake +++ b/lldb/tools/lldb-rpc/LLDBRPCHeaders.cmake @@ -79,7 +79,7 @@ function(FixIncludePaths in subfolder out) 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 + -f lldb_rpc -i ${in} -o ${parked_header} -p ${unifdef_EXECUTABLE} --unifdef_guards SWIG DEPENDS ${in} COMMENT "Fixing includes in ${in}" ) diff --git a/lldb/unittests/Expression/CMakeLists.txt b/lldb/unittests/Expression/CMakeLists.txt index 185b19f..533cdc6 100644 --- a/lldb/unittests/Expression/CMakeLists.txt +++ b/lldb/unittests/Expression/CMakeLists.txt @@ -8,6 +8,8 @@ add_lldb_unittest(ExpressionTests LINK_LIBS lldbCore lldbPluginObjectFileELF + lldbPluginObjectFileWasm + lldbPluginSymbolVendorWasm lldbPluginPlatformLinux lldbPluginExpressionParserClang lldbPluginTypeSystemClang diff --git a/lldb/unittests/Expression/DWARFExpressionTest.cpp b/lldb/unittests/Expression/DWARFExpressionTest.cpp index 819c973..8b1b933 100644 --- a/lldb/unittests/Expression/DWARFExpressionTest.cpp +++ b/lldb/unittests/Expression/DWARFExpressionTest.cpp @@ -7,9 +7,12 @@ //===----------------------------------------------------------------------===// #include "lldb/Expression/DWARFExpression.h" +#include "Plugins/ObjectFile/wasm/ObjectFileWasm.h" #include "Plugins/Platform/Linux/PlatformLinux.h" #include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h" #include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h" +#include "Plugins/SymbolFile/DWARF/SymbolFileWasm.h" +#include "Plugins/SymbolVendor/wasm/SymbolVendorWasm.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "TestingSupport/Symbol/YAMLModuleTester.h" #include "lldb/Core/Debugger.h" @@ -18,27 +21,127 @@ #include "lldb/Core/dwarf.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/StreamString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Testing/Support/Error.h" #include "gtest/gtest.h" -using namespace lldb_private; using namespace lldb_private::plugin::dwarf; +using namespace lldb_private::wasm; +using namespace lldb_private; using namespace llvm::dwarf; +namespace { +struct MockProcess : Process { + MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) + : Process(target_sp, listener_sp) {} + + llvm::StringRef GetPluginName() override { return "mock process"; } + + bool CanDebug(lldb::TargetSP target, bool plugin_specified_by_name) override { + return false; + }; + + Status DoDestroy() override { return {}; } + + void RefreshStateAfterStop() override {} + + bool DoUpdateThreadList(ThreadList &old_thread_list, + ThreadList &new_thread_list) override { + return false; + }; + + size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, + Status &error) override { + for (size_t i = 0; i < size; ++i) + ((char *)buf)[i] = (vm_addr + i) & 0xff; + error.Clear(); + return size; + } +}; + +class MockThread : public Thread { +public: + MockThread(Process &process) : Thread(process, /*tid=*/1), m_reg_ctx_sp() {} + ~MockThread() override { DestroyThread(); } + + void RefreshStateAfterStop() override {} + + lldb::RegisterContextSP GetRegisterContext() override { return m_reg_ctx_sp; } + + lldb::RegisterContextSP + CreateRegisterContextForFrame(StackFrame *frame) override { + return m_reg_ctx_sp; + } + + bool CalculateStopInfo() override { return false; } + + void SetRegisterContext(lldb::RegisterContextSP reg_ctx_sp) { + m_reg_ctx_sp = reg_ctx_sp; + } + +private: + lldb::RegisterContextSP m_reg_ctx_sp; +}; + +class MockRegisterContext : public RegisterContext { +public: + MockRegisterContext(Thread &thread, const RegisterValue ®_value) + : RegisterContext(thread, 0 /*concrete_frame_idx*/), + m_reg_value(reg_value) {} + + void InvalidateAllRegisters() override {} + + size_t GetRegisterCount() override { return 0; } + + const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override { + return &m_reg_info; + } + + size_t GetRegisterSetCount() override { return 0; } + + const RegisterSet *GetRegisterSet(size_t reg_set) override { return nullptr; } + + lldb::ByteOrder GetByteOrder() override { + return lldb::ByteOrder::eByteOrderLittle; + } + + bool ReadRegister(const RegisterInfo *reg_info, + RegisterValue ®_value) override { + reg_value = m_reg_value; + return true; + } + + bool WriteRegister(const RegisterInfo *reg_info, + const RegisterValue ®_value) override { + return false; + } + + uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, + uint32_t num) override { + return num; + } + +private: + RegisterInfo m_reg_info; + RegisterValue m_reg_value; +}; +} // namespace + static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr, lldb::ModuleSP module_sp = {}, DWARFUnit *unit = nullptr, - ExecutionContext *exe_ctx = nullptr) { + ExecutionContext *exe_ctx = nullptr, + RegisterContext *reg_ctx = nullptr) { DataExtractor extractor(expr.data(), expr.size(), lldb::eByteOrderLittle, /*addr_size*/ 4); - llvm::Expected<Value> result = - DWARFExpression::Evaluate(exe_ctx, /*reg_ctx*/ nullptr, module_sp, - extractor, unit, lldb::eRegisterKindLLDB, - /*initial_value_ptr*/ nullptr, - /*object_address_ptr*/ nullptr); + llvm::Expected<Value> result = DWARFExpression::Evaluate( + exe_ctx, reg_ctx, module_sp, extractor, unit, lldb::eRegisterKindLLDB, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr); if (!result) return result.takeError(); @@ -53,7 +156,7 @@ static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr, if (buf.GetByteSize() <= 8) { uint64_t val = 0; memcpy(&val, buf.GetBytes(), buf.GetByteSize()); - return Scalar(llvm::APInt(buf.GetByteSize()*8, val, false)); + return Scalar(llvm::APInt(buf.GetByteSize() * 8, val, false)); } } [[fallthrough]]; @@ -65,8 +168,8 @@ static llvm::Expected<Scalar> Evaluate(llvm::ArrayRef<uint8_t> expr, class DWARFExpressionTester : public YAMLModuleTester { public: - DWARFExpressionTester(llvm::StringRef yaml_data, size_t cu_index) : - YAMLModuleTester(yaml_data, cu_index) {} + DWARFExpressionTester(llvm::StringRef yaml_data, size_t cu_index) + : YAMLModuleTester(yaml_data, cu_index) {} using YAMLModuleTester::YAMLModuleTester; llvm::Expected<Scalar> Eval(llvm::ArrayRef<uint8_t> expr) { @@ -377,30 +480,6 @@ TEST(DWARFExpression, DW_OP_unknown) { TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit0, DW_OP_deref}), llvm::Failed()); - struct MockProcess : Process { - MockProcess(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp) - : Process(target_sp, listener_sp) {} - - llvm::StringRef GetPluginName() override { return "mock process"; } - bool CanDebug(lldb::TargetSP target, - bool plugin_specified_by_name) override { - return false; - }; - Status DoDestroy() override { return {}; } - void RefreshStateAfterStop() override {} - bool DoUpdateThreadList(ThreadList &old_thread_list, - ThreadList &new_thread_list) override { - return false; - }; - size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size, - Status &error) override { - for (size_t i = 0; i < size; ++i) - ((char *)buf)[i] = (vm_addr + i) & 0xff; - error.Clear(); - return size; - } - }; - // Set up a mock process. ArchSpec arch("i386-pc-linux"); Platform::SetHostPlatform( @@ -421,9 +500,9 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_deref) { ExecutionContext exe_ctx(process_sp); // Implicit location: *0x4. - EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, - {}, {}, &exe_ctx), - llvm::HasValue(GetScalar(32, 0x07060504, false))); + EXPECT_THAT_EXPECTED( + Evaluate({DW_OP_lit4, DW_OP_deref, DW_OP_stack_value}, {}, {}, &exe_ctx), + llvm::HasValue(GetScalar(32, 0x07060504, false))); // Memory location: *(*0x4). // Evaluate returns LLDB_INVALID_ADDRESS for all load addresses. EXPECT_THAT_EXPECTED(Evaluate({DW_OP_lit4, DW_OP_deref}, {}, {}, &exe_ctx), @@ -618,10 +697,12 @@ public: return offset - data_offset; } - bool - ParseVendorDWARFOpcode(uint8_t op, const lldb_private::DataExtractor &opcodes, - lldb::offset_t &offset, - std::vector<lldb_private::Value> &stack) const final { + virtual bool ParseVendorDWARFOpcode( + uint8_t op, const lldb_private::DataExtractor &opcodes, + lldb::offset_t &offset, + + RegisterContext *reg_ctx, lldb::RegisterKind reg_kind, + std::vector<lldb_private::Value> &stack) const override { if (op != DW_OP_WASM_location) { return false; } @@ -647,13 +728,14 @@ public: char CustomSymbolFileDWARF::ID; static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp, - DWARFUnit &dwarf_unit) { + DWARFUnit &dwarf_unit, + RegisterContext *reg_ctx) { // Test that expression extensions can be evaluated, for example // DW_OP_WASM_location which is not currently handled by DWARFExpression: EXPECT_THAT_EXPECTED(Evaluate({DW_OP_WASM_location, 0x03, // WASM_GLOBAL:0x03 0x04, 0x00, 0x00, // index:u32 0x00, DW_OP_stack_value}, - module_sp, &dwarf_unit), + module_sp, &dwarf_unit, nullptr, reg_ctx), llvm::HasValue(GetScalar(32, 42, false))); // Test that searches for opcodes work in the presence of extensions: @@ -667,138 +749,331 @@ static auto testExpressionVendorExtensions(lldb::ModuleSP module_sp, TEST(DWARFExpression, Extensions) { const char *yamldata = R"( ---- !ELF +--- !WASM FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_386 -DWARF: - debug_abbrev: - - Table: - - Code: 0x00000001 - Tag: DW_TAG_compile_unit - Children: DW_CHILDREN_no - debug_info: - - Version: 4 - AddrSize: 4 - Entries: - - AbbrCode: 0x1 - - AbbrCode: 0x0 + Version: 0x1 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: + - I32 + ReturnTypes: + - I32 + - Type: FUNCTION + FunctionTypes: [ 0 ] + - Type: TABLE + Tables: + - Index: 0 + ElemType: FUNCREF + Limits: + Flags: [ HAS_MAX ] + Minimum: 0x1 + Maximum: 0x1 + - Type: MEMORY + Memories: + - Flags: [ HAS_MAX ] + Minimum: 0x100 + Maximum: 0x100 + - Type: GLOBAL + Globals: + - Index: 0 + Type: I32 + Mutable: true + InitExpr: + Opcode: I32_CONST + Value: 65536 + - Type: EXPORT + Exports: + - Name: memory + Kind: MEMORY + Index: 0 + - Name: square + Kind: FUNCTION + Index: 0 + - Name: __indirect_function_table + Kind: TABLE + Index: 0 + - Type: CODE + Functions: + - Index: 0 + Locals: + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B + - Type: CUSTOM + Name: name + FunctionNames: + - Index: 0 + Name: square + GlobalNames: + - Index: 0 + Name: __stack_pointer + - Type: CUSTOM + Name: .debug_abbrev + Payload: 011101250E1305030E10171B0E110112060000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042400030E3E0B0B0B000000 + - Type: CUSTOM + Name: .debug_info + Payload: 510000000400000000000401670000001D005E000000000000000A000000020000003C00000002020000003C00000004ED00039F5700000001014D0000000302910C0400000001014D000000000400000000050400 + - Type: CUSTOM + Name: .debug_str + Payload: 696E740076616C756500513A5C70616F6C6F7365764D5346545C6C6C766D2D70726F6A6563745C6C6C64625C746573745C4150495C66756E6374696F6E616C69746965735C6764625F72656D6F74655F636C69656E745C737175617265007371756172652E6300636C616E672076657273696F6E2031382E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A65637420373535303166353336323464653932616166636532663164613639386232343961373239336463372900 + - Type: CUSTOM + Name: .debug_line + Payload: 64000000040020000000010101FB0E0D000101010100000001000001007371756172652E6300000000000005020200000001000502250000000301050A0A010005022C00000005120601000502330000000510010005023A0000000503010005023E000000000101 )"; - SubsystemRAII<FileSystem, HostInfo, TypeSystemClang, ObjectFileELF, - CustomSymbolFileDWARF> + SubsystemRAII<FileSystem, HostInfo, ObjectFileWasm, SymbolVendorWasm> subsystems; + // Set up a wasm target. + ArchSpec arch("wasm32-unknown-unknown-wasm"); + lldb::PlatformSP host_platform_sp = + platform_linux::PlatformLinux::CreateInstance(true, &arch); + ASSERT_TRUE(host_platform_sp); + Platform::SetHostPlatform(host_platform_sp); + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); + ASSERT_TRUE(debugger_sp); + lldb::TargetSP target_sp; + lldb::PlatformSP platform_sp; + debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, + lldb_private::eLoadDependentsNo, + platform_sp, target_sp); + // Set up a mock process and thread. + lldb::ListenerSP listener_sp(Listener::MakeListener("dummy")); + lldb::ProcessSP process_sp = + std::make_shared<MockProcess>(target_sp, listener_sp); + ASSERT_TRUE(process_sp); + MockThread thread(*process_sp); + const uint32_t kExpectedValue = 42; + lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>( + thread, RegisterValue(kExpectedValue)); + thread.SetRegisterContext(reg_ctx_sp); + llvm::Expected<TestFile> file = TestFile::fromYaml(yamldata); EXPECT_THAT_EXPECTED(file, llvm::Succeeded()); - auto module_sp = std::make_shared<Module>(file->moduleSpec()); - auto &symfile = - *llvm::cast<CustomSymbolFileDWARF>(module_sp->GetSymbolFile()); - auto *dwarf_unit = symfile.DebugInfo().GetUnitAtIndex(0); + auto obj_file_sp = module_sp->GetObjectFile()->shared_from_this(); + SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr); + auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0); - testExpressionVendorExtensions(module_sp, *dwarf_unit); + testExpressionVendorExtensions(module_sp, *dwarf_unit, reg_ctx_sp.get()); } -TEST(DWARFExpression, ExtensionsDWO) { +TEST(DWARFExpression, ExtensionsSplitSymbols) { const char *skeleton_yamldata = R"( ---- !ELF +--- !WASM FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_386 -DWARF: - debug_abbrev: - - Table: - - Code: 0x00000001 - Tag: DW_TAG_skeleton_unit - Children: DW_CHILDREN_no - Attributes: - - Attribute: DW_AT_dwo_name - Form: DW_FORM_string - - Attribute: DW_AT_dwo_id - Form: DW_FORM_data4 - debug_info: - - Version: 4 - AddrSize: 4 - Entries: - - AbbrCode: 0x1 - Values: - - CStr: "dwo_unit" - - Value: 0x01020304 - - AbbrCode: 0x0 + Version: 0x1 +Sections: + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: + - I32 + ReturnTypes: + - I32 + - Type: FUNCTION + FunctionTypes: [ 0 ] + - Type: TABLE + Tables: + - Index: 0 + ElemType: FUNCREF + Limits: + Flags: [ HAS_MAX ] + Minimum: 0x1 + Maximum: 0x1 + - Type: MEMORY + Memories: + - Flags: [ HAS_MAX ] + Minimum: 0x100 + Maximum: 0x100 + - Type: GLOBAL + Globals: + - Index: 0 + Type: I32 + Mutable: true + InitExpr: + Opcode: I32_CONST + Value: 65536 + - Type: EXPORT + Exports: + - Name: memory + Kind: MEMORY + Index: 0 + - Name: square + Kind: FUNCTION + Index: 0 + - Name: __indirect_function_table + Kind: TABLE + Index: 0 + - Type: CODE + Functions: + - Index: 0 + Locals: + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B + - Type: CUSTOM + Name: name + FunctionNames: + - Index: 0 + Name: square + GlobalNames: + - Index: 0 + Name: __stack_pointer + - Type: CUSTOM + Name: external_debug_info + Payload: 167371756172652E7761736D2E64656275672E7761736D )"; - // .dwo sections aren't currently supported by dwarfyaml. The dwo_yamldata - // contents where generated by roundtripping the following yaml through - // yaml2obj | obj2yaml and renaming the sections. This works because the - // structure of the .dwo and non-.dwo sections is identical. - // - // --- !ELF - // FileHeader: - // Class: ELFCLASS64 - // Data: ELFDATA2LSB - // Type: ET_EXEC - // Machine: EM_386 - // DWARF: - // debug_abbrev: #.dwo - // - Table: - // - Code: 0x00000001 - // Tag: DW_TAG_compile_unit - // Children: DW_CHILDREN_no - // Attributes: - // - Attribute: DW_AT_dwo_id - // Form: DW_FORM_data4 - // debug_info: #.dwo - // - Version: 4 - // AddrSize: 4 - // Entries: - // - AbbrCode: 0x1 - // Values: - // - Value: 0x0120304 - // - AbbrCode: 0x0 - const char *dwo_yamldata = R"( ---- !ELF + const char *sym_yamldata = R"( +--- !WASM FileHeader: - Class: ELFCLASS64 - Data: ELFDATA2LSB - Type: ET_EXEC - Machine: EM_386 + Version: 0x1 Sections: - - Name: .debug_abbrev.dwo - Type: SHT_PROGBITS - AddressAlign: 0x1 - Content: '0111007506000000' - - Name: .debug_info.dwo - Type: SHT_PROGBITS - AddressAlign: 0x1 - Content: 0D00000004000000000004010403020100 + - Type: TYPE + Signatures: + - Index: 0 + ParamTypes: + - I32 + ReturnTypes: + - I32 + - Type: FUNCTION + FunctionTypes: [ 0 ] + - Type: TABLE + Tables: + - Index: 0 + ElemType: FUNCREF + Limits: + Flags: [ HAS_MAX ] + Minimum: 0x1 + Maximum: 0x1 + - Type: MEMORY + Memories: + - Flags: [ HAS_MAX ] + Minimum: 0x100 + Maximum: 0x100 + - Type: GLOBAL + Globals: + - Index: 0 + Type: I32 + Mutable: true + InitExpr: + Opcode: I32_CONST + Value: 65536 + - Type: EXPORT + Exports: + - Name: memory + Kind: MEMORY + Index: 0 + - Name: square + Kind: FUNCTION + Index: 0 + - Name: __indirect_function_table + Kind: TABLE + Index: 0 + - Type: CODE + Functions: + - Index: 0 + Locals: + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + - Type: I32 + Count: 1 + Body: 2300210141102102200120026B21032003200036020C200328020C2104200328020C2105200420056C210620060F0B + - Type: CUSTOM + Name: name + FunctionNames: + - Index: 0 + Name: square + GlobalNames: + - Index: 0 + Name: __stack_pointer + - Type: CUSTOM + Name: .debug_abbrev + Payload: 011101250E1305030E10171B0E110112060000022E01110112064018030E3A0B3B0B271949133F1900000305000218030E3A0B3B0B49130000042400030E3E0B0B0B000000 + - Type: CUSTOM + Name: .debug_info + Payload: 510000000400000000000401670000001D005E0000000000000004000000020000003C00000002020000003C00000004ED00039F5700000001014D0000000302910C5100000001014D000000000400000000050400 + - Type: CUSTOM + Name: .debug_str + Payload: 696E7400513A5C70616F6C6F7365764D5346545C6C6C766D2D70726F6A6563745C6C6C64625C746573745C4150495C66756E6374696F6E616C69746965735C6764625F72656D6F74655F636C69656E740076616C756500737175617265007371756172652E6300636C616E672076657273696F6E2031382E302E30202868747470733A2F2F6769746875622E636F6D2F6C6C766D2F6C6C766D2D70726F6A65637420373535303166353336323464653932616166636532663164613639386232343961373239336463372900 + - Type: CUSTOM + Name: .debug_line + Payload: 64000000040020000000010101FB0E0D000101010100000001000001007371756172652E6300000000000005020200000001000502250000000301050A0A010005022C00000005120601000502330000000510010005023A0000000503010005023E000000000101 )"; - SubsystemRAII<FileSystem, HostInfo, ObjectFileELF, CustomSymbolFileDWARF> + SubsystemRAII<FileSystem, HostInfo, ObjectFileWasm, SymbolVendorWasm> subsystems; + // Set up a wasm target. + ArchSpec arch("wasm32-unknown-unknown-wasm"); + lldb::PlatformSP host_platform_sp = + platform_linux::PlatformLinux::CreateInstance(true, &arch); + ASSERT_TRUE(host_platform_sp); + Platform::SetHostPlatform(host_platform_sp); + lldb::DebuggerSP debugger_sp = Debugger::CreateInstance(); + ASSERT_TRUE(debugger_sp); + lldb::TargetSP target_sp; + lldb::PlatformSP platform_sp; + debugger_sp->GetTargetList().CreateTarget(*debugger_sp, "", arch, + lldb_private::eLoadDependentsNo, + platform_sp, target_sp); + // Set up a mock process and thread. + lldb::ListenerSP listener_sp(Listener::MakeListener("dummy")); + lldb::ProcessSP process_sp = + std::make_shared<MockProcess>(target_sp, listener_sp); + ASSERT_TRUE(process_sp); + MockThread thread(*process_sp); + const uint32_t kExpectedValue = 42; + lldb::RegisterContextSP reg_ctx_sp = std::make_shared<MockRegisterContext>( + thread, RegisterValue(kExpectedValue)); + thread.SetRegisterContext(reg_ctx_sp); + llvm::Expected<TestFile> skeleton_file = TestFile::fromYaml(skeleton_yamldata); EXPECT_THAT_EXPECTED(skeleton_file, llvm::Succeeded()); - llvm::Expected<TestFile> dwo_file = TestFile::fromYaml(dwo_yamldata); - EXPECT_THAT_EXPECTED(dwo_file, llvm::Succeeded()); - auto skeleton_module_sp = std::make_shared<Module>(skeleton_file->moduleSpec()); - auto &skeleton_symfile = - *llvm::cast<CustomSymbolFileDWARF>(skeleton_module_sp->GetSymbolFile()); - auto dwo_module_sp = std::make_shared<Module>(dwo_file->moduleSpec()); - SymbolFileDWARFDwo dwo_symfile( - skeleton_symfile, dwo_module_sp->GetObjectFile()->shared_from_this(), - 0x0120304); - auto *dwo_dwarf_unit = dwo_symfile.DebugInfo().GetUnitAtIndex(0); + llvm::Expected<TestFile> sym_file = TestFile::fromYaml(sym_yamldata); + EXPECT_THAT_EXPECTED(sym_file, llvm::Succeeded()); + auto sym_module_sp = std::make_shared<Module>(sym_file->moduleSpec()); - testExpressionVendorExtensions(dwo_module_sp, *dwo_dwarf_unit); + auto obj_file_sp = sym_module_sp->GetObjectFile()->shared_from_this(); + SymbolFileWasm sym_file_wasm(obj_file_sp, nullptr); + auto *dwarf_unit = sym_file_wasm.DebugInfo().GetUnitAtIndex(0); + + testExpressionVendorExtensions(sym_module_sp, *dwarf_unit, reg_ctx_sp.get()); } TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) { @@ -828,12 +1103,12 @@ TEST_F(DWARFExpressionMockProcessTest, DW_OP_piece_file_addr) { uint8_t expr[] = {DW_OP_addr, 0x40, 0x0, 0x0, 0x0, DW_OP_piece, 1, DW_OP_addr, 0x50, 0x0, 0x0, 0x0, DW_OP_piece, 1}; DataExtractor extractor(expr, sizeof(expr), lldb::eByteOrderLittle, - /*addr_size*/ 4); + /*addr_size=*/4); llvm::Expected<Value> result = DWARFExpression::Evaluate( - &exe_ctx, /*reg_ctx*/ nullptr, /*module_sp*/ {}, extractor, - /*unit*/ nullptr, lldb::eRegisterKindLLDB, - /*initial_value_ptr*/ nullptr, - /*object_address_ptr*/ nullptr); + &exe_ctx, /*reg_ctx=*/nullptr, /*module_sp=*/{}, extractor, + /*unit=*/nullptr, lldb::eRegisterKindLLDB, + /*initial_value_ptr=*/nullptr, + /*object_address_ptr=*/nullptr); ASSERT_THAT_EXPECTED(result, llvm::Succeeded()); ASSERT_EQ(result->GetValueType(), Value::ValueType::HostAddress); 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; diff --git a/lldb/unittests/Symbol/TestTypeSystemClang.cpp b/lldb/unittests/Symbol/TestTypeSystemClang.cpp index 71930ab..5785767 100644 --- a/lldb/unittests/Symbol/TestTypeSystemClang.cpp +++ b/lldb/unittests/Symbol/TestTypeSystemClang.cpp @@ -869,7 +869,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateConstruction) { CompilerType clang_type = m_ast->CreateFunctionType(int_type, {}, false, 0U); FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, - false); + false, /*asm_label=*/{}); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -900,7 +900,7 @@ TEST_F(TestTypeSystemClang, TestFunctionTemplateInRecordConstruction) { // 2. It is mirroring the behavior of DWARFASTParserClang::ParseSubroutine. FunctionDecl *func = m_ast->CreateFunctionDeclaration( TU, OptionalClangModuleID(), "foo", clang_type, StorageClass::SC_None, - false); + false, /*asm_label=*/{}); TypeSystemClang::TemplateParameterInfos empty_params; // Create the actual function template. @@ -938,7 +938,7 @@ TEST_F(TestTypeSystemClang, TestDeletingImplicitCopyCstrDueToMoveCStr) { bool is_attr_used = false; bool is_artificial = false; m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); @@ -975,7 +975,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { CompilerType function_type = m_ast->CreateFunctionType( return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -987,7 +987,7 @@ TEST_F(TestTypeSystemClang, TestNotDeletingUserCopyCstrDueToMoveCStr) { m_ast->CreateFunctionType(return_type, args, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), class_name, nullptr, function_type, + t.GetOpaqueQualType(), class_name, /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); } @@ -1098,7 +1098,7 @@ TEST_F(TestTypeSystemClang, AddMethodToCXXRecordType_ParmVarDecls) { m_ast->CreateFunctionType(return_type, param_types, /*variadic=*/false, /*quals*/ 0U); m_ast->AddMethodToCXXRecordType( - t.GetOpaqueQualType(), "myFunc", nullptr, function_type, + t.GetOpaqueQualType(), "myFunc", /*asm_label=*/{}, function_type, lldb::AccessType::eAccessPublic, is_virtual, is_static, is_inline, is_explicit, is_attr_used, is_artificial); |